netmon-multinode/MultiNode/MNLib.h

195 lines
4.5 KiB
C

#pragma once
#ifndef MNLib_h
#define MNLib_h
#include <RH_RF95.h>
#include <TemperatureZero.h>
#include <BLAKE2s.h>
#define ON HIGH
#define OFF LOW
#define MODEM_CONFIG RH_RF95::Bw125Cr45Sf128
#define MODEM_POWER 13
#define MODEM_FREQ 868.0
#define HASH_LENGTH 8 // 8 bytes
#define RF_SS_PIN 1
#define RF_IRQ_PIN 0
#define BATMON_PIN A5
#define LOOPEN_PIN 27
#define DIVIDER_mA_per_LSB 2.23 / 4096 / 100 * 1000 // Adding 0.5 LSB and dividing by 4095 would be more accurate (approx. 0.01 % error currently)
#define DIVIDER_V_per_LSB 2.23 / 4096 * (180000 + 51100) / 51100
// The following block is kinda unnecessary
#define A1 A1
#define A2 A2
#define A3 A3
#define GPIO8 8
#define GPIO9 9
#define GPIO4 4
#define GPIO3 3
#define DIGIN38 38
#define DIGIN2 2
#define DIGIN5 5
#define DIGIN11 11
#define MOTOR10 10
#define MOTOR12 12
#define DOUT6 6
#define DOUT7 7
#define N_DEVICES 15
#define CFGMEM 256
#define BROADCAST 0xFFFF
#define ERROR_BLINK_HALF_INTERVAL 100 // 5 Hz
#define CONFIGURATION_ADDRESS 0
#define CONFIGURATION_MEMORY_ADDRESS 256
struct MNConfiguration
{
float modem_frequency;
int8_t modem_power;
uint16_t client_address;
uint16_t server_address;
uint32_t sensor_update_interval;
uint32_t device_update_interval;
uint32_t jitter;
uint8_t devices[N_DEVICES];
uint64_t client_secret_key;
uint64_t server_secret_key;
} __attribute__ ((packed));
static_assert(sizeof(MNConfiguration) == 52, "MNConfiguration has the wrong size! Please edit this in the configurator too");
struct DeviceBase
{
uint8_t class_type;
uint8_t sensor_type;
uint8_t pin;
virtual void loop() = 0;
virtual float getValue() = 0;
virtual void setValue(float value) = 0;
virtual void reset() = 0;
virtual bool doSend() = 0;
virtual void initialize() = 0;
virtual void printStatus() = 0;
virtual size_t size() = 0; // Returns sizeof(T) - 4 (4 for the pointer)
} __attribute__ ((packed));
static_assert(sizeof(DeviceBase) == 7, "Device size wrong");
struct Device : DeviceBase
{
void loop() {}
float getValue()
{
return NAN;
}
void setValue(float value) {}
void reset() {} // For counters / ratemeters and such
bool doSend()
{
return false;
}
void initialize() {}
void printStatus()
{
SerialUSB.println("This is a dummy device");
}
size_t size() // Maybe this can be solved with templates too
{
return sizeof(Device) - 4;
}
} __attribute__ ((packed));
static_assert(sizeof(Device) == 7, "Device size wrong");
struct AnalogInput : Device // 20 Bytes, each device gets about 17.06 bytes on average
{
float min_threshold;
float max_threshold;
float multiplier;
float offset;
bool is_current;
void initialize()
{
Device::initialize();
pinMode(pin, INPUT);
}
float getValue()
{
int value = analogRead(pin);
float converted_value;
if (is_current)
converted_value = value * DIVIDER_mA_per_LSB;
else
converted_value = value * DIVIDER_V_per_LSB;
if (converted_value < min_threshold || converted_value > max_threshold)
return NAN;
else
return converted_value * multiplier + offset;
};
bool doSend() {
return true;
}
void printStatus()
{
SerialUSB.print("AnalogInput on pin A");
SerialUSB.println(pin - 14);
}
size_t size() // Maybe this can be solved with templates too
{
return sizeof(AnalogInput) - 4;
}
} __attribute__ ((packed));
static_assert(sizeof(AnalogInput) == 24, "AnalogInput size wrong");
enum MessageType
{
MT_DeviceStatus = 1,
MT_SensorStatus = 2,
MT_Time = 2,
};
extern MNConfiguration configuration;
extern uint8_t configuration_memory[CFGMEM];
extern RH_RF95 radio;
extern TemperatureZero temperature_sensor;
extern BLAKE2s hash_generator;
extern uint32_t message_id;
extern DeviceBase* devices[N_DEVICES];
//void init_mn(bool is_client);
void initMN();
void test();
void printStatusReport();
void setLoopPower(bool state);
void saveMemory(); // Save everything to flash
void loadMemory(); // Load everything (configuration, cfgmem) from flash
void refreshConfig();
float batteryVoltage();
void errorBlink(int n); // Quickly blink n times
bool send(uint8_t data[], uint8_t len);
bool receive();
void initializeDevices();
DeviceBase* getDeviceFromClass(uint8_t class_type);
DeviceBase* getDevice(uint8_t pointer); // Gets the device at the specified location from cfgmem
void storeDevice(uint8_t pointer, DeviceBase* device); // Stores a device at the specified location in cfgmem (not in flash)
void loopMN();
void sendSensorData();
void sendDeviceData();
void initRTC();
uint32_t getRTC();
#endif