Skip to content

Commit

Permalink
Further refactoring and work on multi sensor support
Browse files Browse the repository at this point in the history
  • Loading branch information
Michael Rüttgers committed Apr 13, 2020
1 parent d3227c9 commit 112bc6c
Show file tree
Hide file tree
Showing 7 changed files with 266 additions and 217 deletions.
2 changes: 1 addition & 1 deletion platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ lib_deps =
IotWebConf
MQTT
lib_ldf_mode = ${common.lib_ldf_mode}
build_flags = ${common.build_flags} -DSERIAL_DEBUG=true -DSERIAL_DEBUG_VERBOSE=false
build_flags = ${common.build_flags} -DSERIAL_DEBUG=true -DSERIAL_DEBUG_VERBOSE=true

[env:d1_mini_dev]
platform = ${common.platform}
Expand Down
7 changes: 4 additions & 3 deletions src/publishers/mqtt_publisher.h → src/MqttPublisher.h
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
#ifndef mqtt_publisher_h
#define mqtt_publisher_h
#ifndef MQTT_PUBLISHER_H
#define MQTT_PUBLISHER_H

#include "config.h"
#include "debug.h"
#include "MQTT.h"
#include <string.h>
#include <sml/sml_file.h>

struct MqttConfig
Expand Down Expand Up @@ -55,7 +56,7 @@ class MqttPublisher
publish(baseTopic + "info", message);
}

void publish(sensor_state *sensor, sml_file *file)
void publish(Sensor *sensor, sml_file *file)
{

for (int i = 0; i < file->messages_len; i++)
Expand Down
231 changes: 231 additions & 0 deletions src/Sensor.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,231 @@
#ifndef SENSOR_H
#define SENSOR_H

#include <SoftwareSerial.h>
#include "debug.h"

// SML constants
const byte START_SEQUENCE[] = {0x1B, 0x1B, 0x1B, 0x1B, 0x01, 0x01, 0x01, 0x01};
const byte END_SEQUENCE[] = {0x1B, 0x1B, 0x1B, 0x1B, 0x1A};
const size_t BUFFER_SIZE = 3840; // Max datagram duration 400ms at 9600 Baud
const uint8_t READ_TIMEOUT = 30;

// States
enum State
{
INIT,
WAIT_FOR_START_SEQUENCE,
READ_MESSAGE,
PROCESS_MESSAGE,
READ_CHECKSUM
};

class SensorConfig
{
public:
const uint8_t pin;
const char *name;
const bool numeric_only;
};

class Sensor
{
public:
const SensorConfig *config;
Sensor(const SensorConfig *config, void (*callback)(byte *buffer, size_t len, Sensor *sensor))
{
this->config = config;
DEBUG("Initializing sensor %s...", this->config->name);
this->callback = callback;
this->serial = new SoftwareSerial();
this->serial->begin(9600, SWSERIAL_8N1, this->config->pin, -1, false, BUFFER_SIZE, BUFFER_SIZE);
this->serial->enableTx(false);
this->serial->enableRx(true);
this->serial->enableIntTx(false);
DEBUG("Initialized sensor %s.", this->config->name);
}
void init()
{
DEBUG("Initializing state of sensor %s...", this->config->name);
this->init_state();
}
void loop()
{
this->run_current_state();
yield();
}

private:
SoftwareSerial *serial;
byte buffer[BUFFER_SIZE];
size_t position = 0;
unsigned long last_state_reset = 0;
uint8_t bytes_until_checksum = 0;
uint8_t loop_counter = 0;
State state = INIT;
void (*callback)(byte *buffer, size_t len, Sensor *sensor) = NULL;

void run_current_state()
{
if (this->state != INIT)
{
if ((millis() - this->last_state_reset) > (READ_TIMEOUT * 1000))
{
DEBUG("Did not receive an SML message within %d seconds, starting over.", READ_TIMEOUT);
this->reset_state();
}
switch (this->state)
{
case WAIT_FOR_START_SEQUENCE:
this->wait_for_start_sequence();
break;
case READ_MESSAGE:
this->read_message();
break;
case PROCESS_MESSAGE:
this->process_message();
break;
case READ_CHECKSUM:
this->read_checksum();
break;
default:
break;
}
}
}

// Wrappers for sensor access
int data_available()
{
return this->serial->available();
}
int data_read()
{
return this->serial->read();
}

// Set state
void set_state(State new_state)
{
if (new_state == WAIT_FOR_START_SEQUENCE)
{
DEBUG("State of sensor %s is 'WAIT_FOR_START_SEQUENCE'.", this->config->name);
this->last_state_reset = millis();
this->position = 0;
}
else if (new_state == READ_MESSAGE)
{
DEBUG("State of sensor %s is 'READ_MESSAGE'.", this->config->name);
}
else if (new_state == READ_CHECKSUM)
{
DEBUG("State of sensor %s is 'READ_CHECKSUM'.", this->config->name);
this->bytes_until_checksum = 3;
}
else if (new_state == PROCESS_MESSAGE)
{
DEBUG("State of sensor %s is 'PROCESS_MESSAGE'.", this->config->name);
};
this->state = new_state;
}

// Initialize state machine
void init_state()
{
this->set_state(WAIT_FOR_START_SEQUENCE);
}

// Start over and wait for the start sequence
void reset_state(const char *message = NULL)
{
if (message != NULL && strlen(message) > 0)
{
DEBUG(message);
}
this->init_state();
}

// Wait for the start_sequence to appear
void wait_for_start_sequence()
{
while (this->data_available())
{
this->buffer[this->position] = this->data_read();
yield();

this->position = (this->buffer[this->position] == START_SEQUENCE[this->position]) ? (this->position + 1) : 0;
if (this->position == sizeof(START_SEQUENCE))
{
// Start sequence has been found
DEBUG("Start sequence found.");
this->set_state(READ_MESSAGE);
return;
}
}
}

// Read the rest of the message
void read_message()
{
while (this->data_available())
{
// Check whether the buffer is still big enough to hold the number of fill bytes (1 byte) and the checksum (2 bytes)
if ((this->position + 3) == BUFFER_SIZE)
{
this->reset_state("Buffer will overflow, starting over.");
return;
}
this->buffer[this->position++] = this->data_read();
yield();

// Check for end sequence
int last_index_of_end_seq = sizeof(END_SEQUENCE) - 1;
for (int i = 0; i <= last_index_of_end_seq; i++)
{
if (END_SEQUENCE[last_index_of_end_seq - i] != this->buffer[this->position - (i + 1)])
{
break;
}
if (i == last_index_of_end_seq)
{
DEBUG("End sequence found.");
this->set_state(READ_CHECKSUM);
return;
}
}
}
}

// Read the number of fillbytes and the checksum
void read_checksum()
{
while (this->bytes_until_checksum > 0 && this->data_available())
{
this->buffer[this->position++] = this->data_read();
this->bytes_until_checksum--;
yield();
}

if (this->bytes_until_checksum == 0)
{
DEBUG("Message has been read.");
DEBUG_DUMP_BUFFER(this->buffer, this->position);
this->set_state(PROCESS_MESSAGE);
}
}

void process_message()
{
// Call listener
if (this->callback != NULL)
{
this->callback(this->buffer, this->position, this);
}
DEBUG("Processing...");

// Start over
this->reset_state();
}
};

#endif
7 changes: 4 additions & 3 deletions src/config.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
#ifndef CONFIG_H
#define CONFIG_H

#include <types.h>
#include "Arduino.h"
#include "Sensor.h"

const char *VERSION = "2.0.0";

Expand All @@ -10,11 +11,11 @@ const char *VERSION = "2.0.0";
const char *CONFIG_VERSION = "1.0.2";
const uint8_t STATUS_PIN = LED_BUILTIN;

static const sensor_config SENSOR_CONFIGS[] = {
static const SensorConfig SENSOR_CONFIGS[] = {
{.pin = D5,
.name = "1",
.numeric_only = false}};

const uint8_t NUM_OF_SENSORS = sizeof(SENSOR_CONFIGS) / sizeof(sensor_config);
const uint8_t NUM_OF_SENSORS = sizeof(SENSOR_CONFIGS) / sizeof(SensorConfig);

#endif
Loading

0 comments on commit 112bc6c

Please sign in to comment.