#pragma once #ifndef MNLib_h #define MNLib_h #include #include #include #define ON HIGH #define OFF LOW #define MODEM_CONFIG RH_RF95::Bw125Cr45Sf128 #define MODEM_POWER 13 #define MODEM_FREQ_LOWER 863 #define MODEM_FREQ_UPPER 870 #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