Fork of the espurna firmware for `mhsw` switches
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

167 lines
3.8 KiB

/*
SENSOR MODULE
Copyright (C) 2016-2019 by Xose Pérez <xose dot perez at gmail dot com>
Copyright (C) 2020 by Maxim Prokhorov <prokhorov dot max at outlook dot com>
*/
#pragma once
#include "espurna.h"
#include "broker.h"
//--------------------------------------------------------------------------------
namespace sensor {
namespace type {
enum Type : unsigned char {
Base = 0,
Emon = 1 << 0,
Analog = 1 << 1
};
} // namespace type
enum class Unit : int {
Min_,
None,
Celcius,
Farenheit,
Kelvin,
Percentage,
Hectopascal,
Ampere,
Volt,
Voltampere,
Kilovoltampere,
VoltampereReactive,
KilovoltampereReactive,
Watt,
Kilowatt,
WattSecond,
Joule = WattSecond,
KilowattHour,
PartsPerMillion,
Ohm,
MicrogrammPerCubicMeter, // The concentration of an air pollutant
MilligrammPerCubicMeter, //
Lux,
UltravioletIndex, // "measurement of the strength of sunburn-producing ultraviolet (UV) radiation at a particular place and time"
// (XXX: Not a unit. Distinguish from None and specify decimals)
CountsPerMinute, // Unit of local dose rate (Geiger counting)
MicrosievertPerHour, // 2nd unit of local dose rate (Geiger counting)
Meter,
Hertz,
Ph,
Max_
};
// Base units are 32 bit since we are the fastest with them.
struct Ws {
Ws();
Ws(uint32_t);
uint32_t value;
};
struct Wh {
Wh();
Wh(Ws);
Wh(uint32_t);
uint32_t value;
};
struct KWh {
KWh();
KWh(Ws);
KWh(Wh);
KWh(uint32_t);
uint32_t value;
};
struct Energy {
constexpr static uint32_t KwhMultiplier = 3600000ul;
constexpr static uint32_t KwhLimit = ((1ul << 31ul) / KwhMultiplier);
Energy() = default;
// TODO: while we accept ws >= the kwh conversion limit,
// should this be dealt with on the unit level?
Energy(double);
Energy(KWh, Ws);
Energy(KWh);
Energy(Wh);
Energy(Ws);
// Sets internal counters to zero
void reset();
// Check whether we have *any* energy recorded. Can be zero:
// - on cold boot
// - on overflow
// - when we call `reset()`
operator bool();
// Generic conversion as-is
double asDouble();
// Convert back to input unit, with overflow mechanics when kwh values goes over 32 bit
Ws asWs();
// Generic sensors output energy in joules / watt-second
Energy& operator +=(Ws);
Energy operator +(Ws);
// But sometimes we want to accept asDouble() value back
Energy& operator =(double);
// We are storing a kind-of integral and fractional parts
// Using watt-second to avoid loosing precision, we don't expect these to be accessed directly
KWh kwh;
Ws ws;
};
struct Value {
double get();
double last;
double reported;
unsigned char decimals;
};
}
BrokerDeclare(SensorReadBroker, void(const String&, unsigned char, double, const char*));
BrokerDeclare(SensorReportBroker, void(const String&, unsigned char, double, const char*));
String magnitudeUnits(unsigned char index);
String magnitudeDescription(unsigned char index);
unsigned char magnitudeType(unsigned char index);
unsigned char magnitudeIndex(unsigned char index);
String magnitudeTopicIndex(unsigned char index);
unsigned char magnitudeCount();
sensor::Value magnitudeValue(unsigned char index);
void magnitudeFormat(const sensor::Value& value, char* output, size_t size);
// XXX: without param name it is kind of vague what exactly unsigned char is
// consider adding stronger param type e.g. enum class
String magnitudeTopic(unsigned char type);
String magnitudeName(unsigned char type);
String sensorError(unsigned char error);
void sensorWebSocketMagnitudes(JsonObject& root, const String& prefix);
unsigned char sensorCount();
void sensorSetup();
void sensorLoop();