initial analog card OOP draft

This commit is contained in:
Siwat Sirichai 2023-12-29 00:39:11 +07:00
parent 75aa6f490b
commit ec7b7f2510
5 changed files with 273 additions and 6 deletions

View File

@ -10,6 +10,47 @@ AnalogCard::AnalogCard() : dac0(DAC0_ADDRESS),
} }
void AnalogCard::dacWrite(uint8_t pin, uint16_t value) void AnalogCard::dacWrite(uint8_t pin, uint16_t value)
{
this->setDACState(pin, value > 0);
this->setDACValue(pin, value);
}
void AnalogCard::setDACState(uint8_t pin, bool state)
{
this->dac_state[pin] = state;
this->sendDataToDAC(pin, this->dac_value[pin]*state);
if (this->dac_change_callback != NULL)
{
this->dac_change_callback(pin, state, this->dac_value[pin]);
}
}
void AnalogCard::setDACValue(uint8_t pin, uint16_t value)
{
this->dac_value[pin] = value;
this->sendDataToDAC(pin, value*this->dac_state[pin]);
if (this->dac_change_callback != NULL)
{
this->dac_change_callback(pin, this->dac_state[pin], value);
}
}
uint16_t AnalogCard::getDACValue(uint8_t pin)
{
return this->dac_value[pin];
}
bool AnalogCard::getDACState(uint8_t pin)
{
return this->dac_state[pin];
}
uint16_t AnalogCard::getDACValue(uint8_t pin)
{
return this->dac_value[pin];
}
void AnalogCard::sendDataToDAC(uint8_t pin, uint16_t value)
{ {
switch (pin) switch (pin)
{ {
@ -85,4 +126,14 @@ void AnalogCard::loop()
uint8_t AnalogCard::getType() uint8_t AnalogCard::getType()
{ {
return CARD_TYPE_ANALOG; return CARD_TYPE_ANALOG;
}
void AnalogCard::registerDACChangeCallback(std::function<void(uint8_t, bool, uint16_t)> callback)
{
this->dac_change_callback = callback;
}
void AnalogCard::deregisterDACChangeCallback()
{
this->dac_change_callback = NULL;
} }

View File

@ -16,11 +16,21 @@ class AnalogCard : public ExpansionCard {
public: public:
AnalogCard(); AnalogCard();
void dacWrite(uint8_t pin, uint16_t value); void dacWrite(uint8_t pin, uint16_t value);
void sendDataToDAC(uint8_t pin, uint16_t value);
uint16_t analogRead(uint8_t pin); uint16_t analogRead(uint8_t pin);
bool begin(); bool begin();
void loop(); void loop();
bool getDACState(uint8_t pin);
uint16_t getDACValue(uint8_t pin);
void setDACState(uint8_t pin, bool state);
void setDACValue(uint8_t pin, uint16_t value);
void registerDACChangeCallback(std::function<void(uint8_t, bool, uint16_t)> callback);
void deregisterDACChangeCallback();
uint8_t getType(); uint8_t getType();
private: private:
std::function<void(uint8_t, bool, uint16_t)> dac_change_callback;
bool dac_state[4];
uint16_t dac_value[4];
MCP4725 dac0; MCP4725 dac0;
MCP4725 dac1; MCP4725 dac1;
MCP4725 dac2; MCP4725 dac2;

View File

@ -0,0 +1,172 @@
#include <AnalogIoT.hpp>
AnalogIoT::AnalogIoT() {
for (uint8_t i = 0; i < 8; i++) {
adc_publish_enabled[i] = false;
adc_conversion_interval[i] = 1000;
}
}
AnalogIoT::~AnalogIoT() {
}
bool AnalogIoT::begin(uint8_t card_id, ExpansionCard *card, PubSubClient *mqtt, char *base_topic) {
this->mqtt = mqtt;
this->base_topic = base_topic;
this->card = (AnalogCard*)card;
this-> card_id = card_id;
this->dac_set_state_length = strlen(DAC_SET_STATE_TOPIC);
this->dac_set_value_length = strlen(DAC_SET_VALUE_TOPIC);
this->dac_state_length = strlen(DAC_STATE_TOPIC);
this->dac_value_length = strlen(DAC_VALUE_TOPIC);
this->request_state_length = strlen(REQUEST_STATE_TOPIC);
this->dac_publish_enable_length = strlen(DAC_PUBLISH_ENABLE_TOPIC);
// Register callbacks
auto bindedCallback = std::bind(&AnalogIoT::handleDACChange, this, std::placeholders::_1, std::placeholders::_2);
this->card->registerDACChangeCallback(bindedCallback);
return true;
}
void AnalogIoT::handleMqttMessage(char *topic, char *payload){
uint8_t topic_length = strlen(topic);
if(this-> processDACSetStateMessage(topic, payload, topic_length)) return;
if(this-> processDACSetValueMessage(topic, payload, topic_length)) return;
if(this-> processRequestStateMessage(topic, payload, topic_length)) return;
if(this-> processADCSetConversionIntervalMessage(topic, payload, topic_length)) return;
if(this-> processADCSetConversionEnabledMessage(topic, payload, topic_length)) return;
}
void AnalogIoT::publishADCs() {
for (uint8_t i = 0; i < 8; i++) {
this->publishADC(i);
}
}
void AnalogIoT::publishADC(uint8_t pin) {
if (this->adc_publish_enabled[pin]) {
uint16_t value = this->card->analogRead(pin);
char *topic = new char[15];
sprintf(topic, "adc/%02d/value", pin);
char *payload = new char[10];
sprintf(payload, "%d", value);
this->publishRelative(topic, payload);
delete[] topic;
delete[] payload;
}
}
void AnalogIoT::setADCsPublishInterval(uint32_t interval) {
for (uint8_t i = 0; i < 8; i++) {
adc_conversion_interval[i] = interval;
}
}
void AnalogIoT::setADCsPublishEnabled(bool enabled) {
for (uint8_t i = 0; i < 8; i++) {
adc_publish_enabled[i] = enabled;
}
}
void AnalogIoT::registerDACChangeCallback(std::function<void(uint8_t, uint16_t)> callback) {
dac_change_callback = callback;
}
void AnalogIoT::deregisterDACChangeCallback() {
dac_change_callback = NULL;
}
void AnalogIoT::registerADCConversionCallback(std::function<void(uint8_t, uint16_t)> callback) {
adc_conversion_callback = callback;
}
void AnalogIoT::deregisterADCConversionCallback() {
adc_conversion_callback = NULL;
}
void AnalogIoT::setADCConversionInterval(uint8_t pin, uint16_t interval) {
adc_conversion_interval[pin] = interval;
}
void AnalogIoT::setADCConversionEnabled(uint8_t pin, bool enabled) {
adc_publish_enabled[pin] = enabled;
}
bool AnalogIoT::processADCSetConversionIntervalMessage(char *topic, char *payload, uint8_t topic_length) {
// TODO: publish all DACs and ADCs
}
bool AnalogIoT::processADCSetConversionEnabledMessage(char *topic, char *payload, uint8_t topic_length) {
// TODO: publish all DACs and ADCs
}
bool AnalogIoT::processDACSetStateMessage(char *topic, char *payload, uint8_t topic_length) {
// TODO: publish all DACs and ADCs
}
bool AnalogIoT::processDACSetValueMessage(char *topic, char *payload, uint8_t topic_length) {
// TODO: publish all DACs and ADCs
}
bool AnalogIoT::processRequestStateMessage(char *topic, char *payload, uint8_t topic_length) {
// TODO: publish all DACs and ADCs
}
void AnalogIoT::publishReport() {
// TODO: publish all DACs and ADCs
}
void AnalogIoT::subscribe() {
// There are 4 DACs and 8 ADCs
// DACs: dac/<%02d>/set/state, dac/<%02d>/set/value, dac/publish_enable
// ADCs: adc/<%02d>/set/conversion_interval, adc/<%02d>/set/conversion_enabled
// Subscribe to all set state topics
char topic[20];
for (uint8_t i = 0; i < 4; i++) {
sprintf(topic, "dac/%02d/set/state", i);
this->subscribeRelative(topic);
}
// Subscribe to all set value topics
for (uint8_t i = 0; i < 4; i++) {
sprintf(topic, "dac/%02d/set/value", i);
this->subscribeRelative(topic);
}
// Subscribe to all set conversion interval topics
for (uint8_t i = 0; i < 8; i++) {
sprintf(topic, "adc/%02d/set/conversion_interval", i);
this->subscribeRelative(topic);
}
// Subscribe to all set conversion enabled topics
for (uint8_t i = 0; i < 8; i++) {
sprintf(topic, "adc/%02d/set/conversion_enabled", i);
this->subscribeRelative(topic);
}
// Subscribe to publish enable topic
this->subscribeRelative("dac/publish_enable");
}
void AnalogIoT::loop() {
// Iterate over all ADCs and publish if enabled and interval has passed
uint32_t now = millis();
for (uint8_t i = 0; i < 8; i++) {
if (this->adc_publish_enabled[i] && now - this->last_adc_publish > this->adc_conversion_interval[i]) {
this->publishADC(i);
this->last_adc_publish = now;
}
}
}
void AnalogIoT::publishReport() {
publishADCs();
publishDACs();
}
uint8_t AnalogIoT::getType() {
return CARD_TYPE_ANALOG;
}
void AnalogIoT::publishDACs() {
for (uint8_t i = 0; i < 4; i++) {
this->publishDAC(i);
}
}
void AnalogIoT::publishDAC(uint8_t pin) {
this->publishDACState(pin);
this->publishDACValue(pin);
}
void AnalogIoT::publishDACState(uint8_t pin) {
char *topic = new char[15];
sprintf(topic, "dac/%02d/state", pin);
char *payload = new char[2];
sprintf(payload, "%d", this->card->getDACState(pin));
this->publishRelative(topic, payload);
delete[] topic;
delete[] payload;
}
void AnalogIoT::publishDACValue(uint8_t pin) {
char *topic = new char[15];
sprintf(topic, "dac/%02d/value", pin);
char *payload = new char[5];
sprintf(payload, "%d", this->card->getDACValue(pin));
this->publishRelative(topic, payload);
delete[] topic;
delete[] payload;
}

View File

@ -1,23 +1,58 @@
#pragma once #pragma once
#include <IoTComponent.hpp> #include <IoTComponent.hpp>
#include <AnalogCard.hpp> #include <AnalogCard.hpp>
#define DAC_SET_STATE_TOPIC "/set/state"
#define DAC_SET_VALUE_TOPIC "/set/value"
#define DAC_STATE_TOPIC "/dac/00/state"
#define DAC_VALUE_TOPIC "/dac/00/value"
#define DAC_PUBLISH_ENABLE_TOPIC "/publish_enable"
#define REQUEST_STATE_TOPIC "requeststate"
class AnalogIoT : public IoTComponent { class AnalogIoT : public IoTComponent {
public: public:
AnalogIoT(); AnalogIoT();
~AnalogIoT(); ~AnalogIoT();
bool begin(uint8_t card_id, AnalogCard *card, PubSubClient *mqtt, char *base_topic); bool begin(uint8_t card_id, ExpansionCard *card, PubSubClient *mqtt, char *base_topic);
void handleMqttMessage(char *topic, char *payload); void handleMqttMessage(char *topic, char *payload);
void handleDACChange(uint8_t pin, uint16_t value);
void publishADCs(); void publishADCs();
void publishADC(uint8_t pin);
void publishDACs();
void publishDAC(uint8_t pin);
void publishDACState(uint8_t pin);
void publishDACValue(uint8_t pin);
void setADCsPublishInterval(uint32_t interval); void setADCsPublishInterval(uint32_t interval);
void setADCsPublishEnabled(bool enabled); void setADCsPublishEnabled(bool enabled);
void registerDACChangeCallback(std::function<void(uint8_t, uint16_t)> callback);
void deregisterDACChangeCallback();
void registerADCConversionCallback(std::function<void(uint8_t, uint16_t)> callback);
void deregisterADCConversionCallback();
void setADCConversionInterval(uint8_t pin, uint16_t interval);
void setADCConversionEnabled(uint8_t pin, bool enabled);
bool processADCSetConversionIntervalMessage(char *topic, char *payload, uint8_t topic_length);
bool processADCSetConversionEnabledMessage(char *topic, char *payload, uint8_t topic_length);
bool processDACSetStateMessage(char *topic, char *payload, uint8_t topic_length);
bool processDACSetValueMessage(char *topic, char *payload, uint8_t topic_length);
bool processRequestStateMessage(char *topic, char *payload, uint8_t topic_length);
void publishReport();
void subscribe();
void loop();
void publishReport(); void publishReport();
void subscribe(); void subscribe();
uint8_t getType(); uint8_t getType();
private: private:
char *adc_topic; uint8_t dac_set_state_length;
char *dac_topic; uint8_t dac_set_value_length;
uint32_t adc_publish_interval = 1000; uint8_t dac_state_length;
uint8_t dac_value_length;
uint8_t request_state_length;
uint8_t dac_publish_enable_length;
uint32_t last_adc_publish = 0; uint32_t last_adc_publish = 0;
bool adc_publish_enabled = false;
AnalogCard *card; AnalogCard *card;
bool adc_publish_enabled[8];
uint16_t adc_conversion_interval[8];
uint32_t last_adc_conversion[8];
std::function<void(uint8_t, uint16_t)> dac_change_callback;
std::function<void(uint8_t, uint16_t)> adc_conversion_callback;
}; };

View File

@ -15,7 +15,6 @@ bool DigitalOutputIoT::begin(uint8_t card_id, ExpansionCard *card, PubSubClient
this->mqtt = mqtt; this->mqtt = mqtt;
this->base_topic = base_topic; this->base_topic = base_topic;
this->card = (DigitalOutputCard *) card; this->card = (DigitalOutputCard *) card;
if(!card->begin()) return false;
this-> card_id = card_id; this-> card_id = card_id;
this->set_state_length = strlen(SET_STATE_TOPIC); this->set_state_length = strlen(SET_STATE_TOPIC);
this->set_value_length = strlen(SET_VALUE_TOPIC); this->set_value_length = strlen(SET_VALUE_TOPIC);