Initial commit
This commit is contained in:
37
include/README
Normal file
37
include/README
Normal file
@@ -0,0 +1,37 @@
|
||||
|
||||
This directory is intended for project header files.
|
||||
|
||||
A header file is a file containing C declarations and macro definitions
|
||||
to be shared between several project source files. You request the use of a
|
||||
header file in your project source file (C, C++, etc) located in `src` folder
|
||||
by including it, with the C preprocessing directive `#include'.
|
||||
|
||||
```src/main.c
|
||||
|
||||
#include "header.h"
|
||||
|
||||
int main (void)
|
||||
{
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
Including a header file produces the same results as copying the header file
|
||||
into each source file that needs it. Such copying would be time-consuming
|
||||
and error-prone. With a header file, the related declarations appear
|
||||
in only one place. If they need to be changed, they can be changed in one
|
||||
place, and programs that include the header file will automatically use the
|
||||
new version when next recompiled. The header file eliminates the labor of
|
||||
finding and changing all the copies as well as the risk that a failure to
|
||||
find one copy will result in inconsistencies within a program.
|
||||
|
||||
In C, the convention is to give header files names that end with `.h'.
|
||||
|
||||
Read more about using header files in official GCC documentation:
|
||||
|
||||
* Include Syntax
|
||||
* Include Operation
|
||||
* Once-Only Headers
|
||||
* Computed Includes
|
||||
|
||||
https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html
|
||||
6
include/compressor.h
Normal file
6
include/compressor.h
Normal file
@@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
bool compressBuffer(const uint8_t *in, size_t in_len, uint8_t *out, size_t out_max, size_t &out_len);
|
||||
bool decompressBuffer(const uint8_t *in, size_t in_len, uint8_t *out, size_t out_max, size_t &out_len);
|
||||
58
include/config.h
Normal file
58
include/config.h
Normal file
@@ -0,0 +1,58 @@
|
||||
#pragma once
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
enum class DeviceRole : uint8_t {
|
||||
Sender = 0,
|
||||
Receiver = 1
|
||||
};
|
||||
|
||||
enum class PayloadType : uint8_t {
|
||||
MeterData = 0,
|
||||
TestCode = 1,
|
||||
TimeSync = 2
|
||||
};
|
||||
|
||||
constexpr uint8_t PROTOCOL_VERSION = 1;
|
||||
|
||||
// Pin definitions
|
||||
constexpr uint8_t PIN_LORA_SCK = 5;
|
||||
constexpr uint8_t PIN_LORA_MISO = 19;
|
||||
constexpr uint8_t PIN_LORA_MOSI = 27;
|
||||
constexpr uint8_t PIN_LORA_NSS = 18;
|
||||
constexpr uint8_t PIN_LORA_RST = 23;
|
||||
constexpr uint8_t PIN_LORA_DIO0 = 26;
|
||||
|
||||
constexpr uint8_t PIN_OLED_SDA = 21;
|
||||
constexpr uint8_t PIN_OLED_SCL = 22;
|
||||
constexpr uint8_t PIN_OLED_RST = 16;
|
||||
constexpr uint8_t OLED_I2C_ADDR = 0x3C;
|
||||
constexpr uint8_t OLED_WIDTH = 128;
|
||||
constexpr uint8_t OLED_HEIGHT = 64;
|
||||
|
||||
constexpr uint8_t PIN_BAT_ADC = 35;
|
||||
|
||||
constexpr uint8_t PIN_ROLE = 13;
|
||||
constexpr uint8_t PIN_OLED_CTRL = 14;
|
||||
|
||||
constexpr uint8_t PIN_METER_RX = 34;
|
||||
|
||||
// LoRa settings
|
||||
constexpr long LORA_FREQUENCY = 433E6;
|
||||
constexpr uint8_t LORA_SPREADING_FACTOR = 12;
|
||||
constexpr long LORA_BANDWIDTH = 125E3;
|
||||
constexpr uint8_t LORA_CODING_RATE = 5;
|
||||
constexpr uint8_t LORA_SYNC_WORD = 0x34;
|
||||
|
||||
// Timing
|
||||
constexpr uint32_t SENDER_WAKE_INTERVAL_SEC = 30;
|
||||
constexpr uint32_t TIME_SYNC_INTERVAL_SEC = 60;
|
||||
constexpr uint32_t OLED_PAGE_INTERVAL_MS = 10000;
|
||||
constexpr uint32_t OLED_AUTO_OFF_MS = 10UL * 60UL * 1000UL;
|
||||
|
||||
constexpr uint8_t NUM_SENDERS = 1;
|
||||
inline constexpr uint16_t EXPECTED_SENDER_IDS[NUM_SENDERS] = {
|
||||
0xF19C
|
||||
};
|
||||
|
||||
DeviceRole detect_role();
|
||||
24
include/data_model.h
Normal file
24
include/data_model.h
Normal file
@@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
struct MeterData {
|
||||
uint32_t ts_utc;
|
||||
uint16_t short_id;
|
||||
char device_id[16];
|
||||
float energy_total_kwh;
|
||||
float phase_power_w[3];
|
||||
float total_power_w;
|
||||
float phase_voltage_v[3];
|
||||
float battery_voltage_v;
|
||||
uint8_t battery_percent;
|
||||
bool valid;
|
||||
};
|
||||
|
||||
struct SenderStatus {
|
||||
MeterData last_data;
|
||||
uint32_t last_update_ts_utc;
|
||||
bool has_data;
|
||||
};
|
||||
|
||||
void init_device_ids(uint16_t &short_id, char *device_id, size_t device_id_len);
|
||||
19
include/display_ui.h
Normal file
19
include/display_ui.h
Normal file
@@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#include <Arduino.h>
|
||||
#include "config.h"
|
||||
#include "data_model.h"
|
||||
|
||||
void display_init();
|
||||
void display_set_role(DeviceRole role);
|
||||
void display_set_self_ids(uint16_t short_id, const char *device_id);
|
||||
void display_set_sender_statuses(const SenderStatus *statuses, uint8_t count);
|
||||
void display_set_last_meter(const MeterData &data);
|
||||
void display_set_last_read(bool ok, uint32_t ts_utc);
|
||||
void display_set_last_tx(bool ok, uint32_t ts_utc);
|
||||
void display_set_receiver_status(bool ap_mode, const char *ssid, bool mqtt_ok);
|
||||
void display_tick();
|
||||
#ifdef ENABLE_TEST_MODE
|
||||
void display_set_test_code(const char *code);
|
||||
void display_set_test_code_for_sender(uint8_t index, const char *code);
|
||||
#endif
|
||||
7
include/json_codec.h
Normal file
7
include/json_codec.h
Normal file
@@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <Arduino.h>
|
||||
#include "data_model.h"
|
||||
|
||||
bool meterDataToJson(const MeterData &data, String &out_json);
|
||||
bool jsonToMeterData(const String &json, MeterData &data);
|
||||
19
include/lora_transport.h
Normal file
19
include/lora_transport.h
Normal file
@@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#include <Arduino.h>
|
||||
#include "config.h"
|
||||
|
||||
constexpr size_t LORA_MAX_PAYLOAD = 200;
|
||||
|
||||
struct LoraPacket {
|
||||
uint8_t protocol_version;
|
||||
DeviceRole role;
|
||||
uint16_t device_id_short;
|
||||
PayloadType payload_type;
|
||||
uint8_t payload[LORA_MAX_PAYLOAD];
|
||||
size_t payload_len;
|
||||
};
|
||||
|
||||
void lora_init();
|
||||
bool lora_send(const LoraPacket &pkt);
|
||||
bool lora_receive(LoraPacket &pkt, uint32_t timeout_ms);
|
||||
7
include/meter_driver.h
Normal file
7
include/meter_driver.h
Normal file
@@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <Arduino.h>
|
||||
#include "data_model.h"
|
||||
|
||||
void meter_init();
|
||||
bool meter_read(MeterData &data);
|
||||
13
include/mqtt_client.h
Normal file
13
include/mqtt_client.h
Normal file
@@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include <Arduino.h>
|
||||
#include "data_model.h"
|
||||
#include "wifi_manager.h"
|
||||
|
||||
void mqtt_init(const WifiMqttConfig &config, const char *device_id);
|
||||
void mqtt_loop();
|
||||
bool mqtt_is_connected();
|
||||
bool mqtt_publish_state(const MeterData &data);
|
||||
#ifdef ENABLE_TEST_MODE
|
||||
bool mqtt_publish_test(const char *device_id, const String &payload);
|
||||
#endif
|
||||
9
include/power_manager.h
Normal file
9
include/power_manager.h
Normal file
@@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include <Arduino.h>
|
||||
#include "data_model.h"
|
||||
|
||||
void power_sender_init();
|
||||
void power_receiver_init();
|
||||
void read_battery(MeterData &data);
|
||||
void go_to_deep_sleep(uint32_t seconds);
|
||||
9
include/test_mode.h
Normal file
9
include/test_mode.h
Normal file
@@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include <Arduino.h>
|
||||
#include "data_model.h"
|
||||
|
||||
#ifdef ENABLE_TEST_MODE
|
||||
void test_sender_loop(uint16_t short_id, const char *device_id);
|
||||
void test_receiver_loop(SenderStatus *statuses, uint8_t count);
|
||||
#endif
|
||||
12
include/time_manager.h
Normal file
12
include/time_manager.h
Normal file
@@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include <Arduino.h>
|
||||
#include "lora_transport.h"
|
||||
|
||||
void time_receiver_init(const char *ntp_server_1, const char *ntp_server_2);
|
||||
uint32_t time_get_utc();
|
||||
bool time_is_synced();
|
||||
void time_set_utc(uint32_t epoch);
|
||||
void time_send_timesync(uint16_t device_id_short);
|
||||
bool time_handle_timesync_payload(const uint8_t *payload, size_t len);
|
||||
void time_get_local_hhmm(char *out, size_t out_len);
|
||||
10
include/web_server.h
Normal file
10
include/web_server.h
Normal file
@@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include <Arduino.h>
|
||||
#include "data_model.h"
|
||||
#include "wifi_manager.h"
|
||||
|
||||
void web_server_begin_ap(const SenderStatus *statuses, uint8_t count);
|
||||
void web_server_begin_sta(const SenderStatus *statuses, uint8_t count);
|
||||
void web_server_set_config(const WifiMqttConfig &config);
|
||||
void web_server_loop();
|
||||
25
include/wifi_manager.h
Normal file
25
include/wifi_manager.h
Normal file
@@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <Preferences.h>
|
||||
|
||||
struct WifiMqttConfig {
|
||||
String ssid;
|
||||
String password;
|
||||
String mqtt_host;
|
||||
uint16_t mqtt_port;
|
||||
String mqtt_user;
|
||||
String mqtt_pass;
|
||||
String ntp_server_1;
|
||||
String ntp_server_2;
|
||||
bool valid;
|
||||
};
|
||||
|
||||
void wifi_manager_init();
|
||||
bool wifi_load_config(WifiMqttConfig &config);
|
||||
bool wifi_save_config(const WifiMqttConfig &config);
|
||||
|
||||
bool wifi_connect_sta(const WifiMqttConfig &config, uint32_t timeout_ms = 10000);
|
||||
void wifi_start_ap(const char *ap_ssid, const char *ap_pass);
|
||||
bool wifi_is_connected();
|
||||
String wifi_get_ssid();
|
||||
Reference in New Issue
Block a user