Skip to content

Commit

Permalink
work in progress, restructured everything, missing led output and cor…
Browse files Browse the repository at this point in the history
…rect state transitions for controller
  • Loading branch information
Claypuppet committed Dec 29, 2019
1 parent d939dfd commit 6703c02
Show file tree
Hide file tree
Showing 41 changed files with 682 additions and 1,920 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -527,7 +527,7 @@ node_modules/
**/*.Server/ModelManifest.xml
_Pvt_Extensions

# Paket dependency manager
# Paket dependency controller
.paket/paket.exe
paket-files/

Expand Down
120 changes: 80 additions & 40 deletions bgeigiecast/api_connector.cpp
Original file line number Diff line number Diff line change
@@ -1,68 +1,105 @@

#include "api_connector.h"
#include "debugger.h"
#include "identifiers.h"

#define API_SEND(alert) (alert ? API_SEND_FREQUENCY_SECONDS_ALERT : API_SEND_FREQUENCY_SECONDS)
#define API_SEND_DEV(alert) (alert ? API_SEND_FREQUENCY_SECONDS_ALERT_DEV : API_SEND_FREQUENCY_SECONDS_DEV)
#define API_SEND_FREQUENCY(alert, dev) (((dev ? API_SEND_DEV(alert) : API_SEND(alert)) * 1000) - 2000)

ApiReporter::ApiReporter(LocalStorage& config) :
Handler(k_handler_api_reporter),
_config(config),
_saved_readings(),
_last_send(),
_merged_reading(),
_current_default_response(e_api_reporter_idle),
_alert() {
}

#define API_SEND_FREQUENCY (API_SEND_FREQUENCY_MINUTES * 60 * 1000)
bool ApiReporter::is_connected() const {
return WiFi.status() == WL_CONNECTED;
}

ApiConnector::ApiConnector(EspConfig& config, ApiConnectionObserver* observer) : IApiConnector(config, observer) {
bool ApiReporter::time_to_send() const {
return millis() - _last_send > API_SEND_FREQUENCY(_alert, _config.get_use_dev());
}

bool ApiConnector::start_connect(bool initial) {
if(is_connected()) {
return true;
void ApiReporter::save_reading() {
DEBUG_PRINTLN("Could not upload reading, trying again later");
if(_merged_reading.valid_reading()) {
_saved_readings.add(_merged_reading);
}
}

const char* ssid = _config.get_wifi_ssid();
if(!ssid) {
DEBUG_PRINTLN("No SSID to connect to!");
return false;
}
void ApiReporter::reset() {
_last_send = millis();
_merged_reading.reset();
}

DEBUG_PRINTLN();
bool ApiReporter::activate(bool retry) {
if(is_connected()) {
return true;
}

if(initial) {
if(retry) {
WiFi.reconnect();
} else {
const char* ssid = _config.get_wifi_ssid();
if(!ssid) {
DEBUG_PRINTLN("No SSID to connect to!");
return false;
}
const char* password = _config.get_wifi_password();
DEBUG_PRINT("Connecting to ssid ");
DEBUG_PRINTLN(ssid);
password ? WiFi.begin(ssid, password) : WiFi.begin(ssid);
_merged_reading.reset();
_last_send = millis();
} else {
WiFi.reconnect();
}

return is_connected();
}

void ApiConnector::stop() {
void ApiReporter::deactivate() {
reset();
WiFi.disconnect(true, true);
WiFi.mode(WIFI_MODE_NULL);
}

bool ApiConnector::test() {
WiFiClient client;
bool success = client.connect(API_HOST, 80) != 0;
client.stop();
return success;
}
int8_t ApiReporter::handle_produced_work(const worker_status_t& worker_reports) {
const auto& reader = worker_reports.at(k_worker_bgeigie_connector);
if(!reader.is_fresh()) {
return _current_default_response;
}
const auto& reading = reader.get<Reading>();
_merged_reading += reading;
if(!time_to_send()) {
return _current_default_response;
}

bool ApiConnector::is_connected() {
return WiFi.status() == WL_CONNECTED;
_last_send = millis();
if(_config.get_use_home_location()) {
_merged_reading.apply_home_location(_config.get_home_latitude(), _config.get_home_longitude());
}

if(_merged_reading.valid_reading()) {
_current_default_response = send_reading(reading);
} else {
return e_api_reporter_error_invalid_reading;
}
reset();
}

bool ApiConnector::send_reading() {
ApiReporter::ApiHandlerStatus ApiReporter::send_reading(const Reading& reading) {
char json_str[200];
if(!_merged_reading.as_json(json_str)) {
// This whole reading is invalid
DEBUG_PRINTLN("Unable to send reading, its not valid at all!");
schedule_event(e_a_api_post_failed);
return false;
return e_api_reporter_error_invalid_reading;
}

if(!is_connected()) {
if(!is_connected() && !activate(true)) {
DEBUG_PRINTLN("Unable to send, lost connection");
schedule_event(e_a_api_post_failed);
return false;
return e_api_reporter_error_not_connected;
}

HTTPClient http;
Expand All @@ -77,9 +114,8 @@ bool ApiConnector::send_reading() {
//Specify destination for HTTP request
if(!http.begin(url)) {
DEBUG_PRINTLN("Unable to begin url connection");
save_reading();
http.end(); //Free resources
return false;
return e_api_reporter_error_remote_not_available;
}

char content_length[5];
Expand All @@ -96,18 +132,22 @@ bool ApiConnector::send_reading() {

int httpResponseCode = http.POST(json_str); //Send the actual POST request

if(httpResponseCode > 0) {
if(httpResponseCode >= 200 && httpResponseCode < 300) {
String response = http.getString();
DEBUG_PRINTLN("POST successfull");
DEBUG_PRINT(httpResponseCode);
DEBUG_PRINTLN(response);
schedule_event(e_a_reading_posted);
http.end(); //Free resources
return true;
return e_api_reporter_send_success;
} else if(httpResponseCode > 0) {
DEBUG_PRINTLN("Remote error on sending POST");
http.end(); //Free resources
return e_api_reporter_error_server_rejected_post;
} else {
DEBUG_PRINTLN("Error on sending POST");
// Failed to send
schedule_event(e_a_api_post_failed);
DEBUG_PRINTLN("Remote not available");
http.end(); //Free resources
return false;
// Failed to send
return e_api_reporter_error_remote_not_available;

}
}
71 changes: 54 additions & 17 deletions bgeigiecast/api_connector.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,48 +4,85 @@
#include <WiFi.h>
#include <HTTPClient.h>

#include "i_api_connector.h"
#include <Handler.hpp>

#include "local_storage.h"
#include "reading.h"
#include "user_config.h"
#include "circular_buffer.h"

/**
* Connects over WiFi to the API to send readings
*/
class ApiConnector : public IApiConnector {
class ApiReporter : public Handler {
public:

explicit ApiConnector(EspConfig& config, ApiConnectionObserver* observer = nullptr);
virtual ~ApiConnector() = default;
enum ApiHandlerStatus {
e_api_reporter_idle,
e_api_reporter_send_success,
e_api_reporter_error_invalid_reading,
e_api_reporter_error_not_connected,
e_api_reporter_error_remote_not_available,
e_api_reporter_error_server_rejected_post,
};

explicit ApiReporter(LocalStorage& config);
virtual ~ApiReporter() = default;

/**
* Initialize the connection
* @param initial: set to false if its for reconnect / connect in error
* @return true if connection with the wifi was made
* Check if the connection is up
* @return true if connected
*/
bool start_connect(bool initial) override;
bool is_connected() const;
protected:

/**
* Disconnect
* Check if enough time has passed to send the latest reading to api
* @return
*/
void stop() override;
bool time_to_send() const;

/**
* Test the connection to the API
* reset the api time and merged readings
*/
bool test() override;
void reset();

/**
* Check if the connection is up
* @return true if connected
* Initialize the connection
* @param initial: set to false if its for reconnect / connect in error
* @return true if connection with the wifi was made
*/
bool is_connected() override;
bool activate(bool retry) override;

protected:
/**
* Stop the connection
*/
void deactivate() override;

int8_t handle_produced_work(const worker_status_t& worker_reports) override;
/**
* When a reading cannot be send to the API, we save it to send later..
* @param reading: reading to save
*/
virtual void save_reading() final;

private:

/**
* Send a reading to the API
* @param reading: reading to send
* @return: true if the API call was successful
*/
bool send_reading() override;
ApiHandlerStatus send_reading(const Reading& reading);


LocalStorage& _config;
CircularBuffer<Reading, MAX_MISSED_READINGS> _saved_readings;
uint32_t _last_send;
Reading _merged_reading;
ApiHandlerStatus _current_default_response;

bool _alert;
};

#endif //BGEIGIECAST_APICONNECTOR_H
16 changes: 9 additions & 7 deletions bgeigiecast/bgeigie_connector.cpp
Original file line number Diff line number Diff line change
@@ -1,20 +1,22 @@
#include "bgeigie_connector.h"
#include "user_config.h"
#include "debugger.h"
#include "identifiers.h"

BGeigieConnector::BGeigieConnector(Stream& serial_connection) : _serial_connection(serial_connection), _buffer("") {
BGeigieConnector::BGeigieConnector(Stream& serial_connection) :
Worker<Reading>(k_worker_bgeigie_connector, Reading(), 4000),
_serial_connection(serial_connection),
_buffer("") {
}

bool BGeigieConnector::get_reading(Reading& out) {
int8_t BGeigieConnector::produce_data() {
while(_serial_connection.available() > 0) {
char c = static_cast<char>(_serial_connection.read());
_buffer += c;
if(c == '\n') {
// DEBUG_PRINT("New reading: "); DEBUG_PRINT(_buffer);
out = _buffer.c_str();
_buffer = "";
return true;
data = _buffer.c_str();
return data.get_status() | k_reading_parsed ? WorkerStatus::e_worker_data_read : WorkerStatus::e_worker_error;
}
}
return false;
return WorkerStatus::e_worker_idle;
}
12 changes: 5 additions & 7 deletions bgeigiecast/bgeigie_connector.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,20 @@

#include <Arduino.h>

#include <Worker.hpp>

#include "reading.h"

/**
* Connect the system to the bGeigieNano to read sensor data
*/
class BGeigieConnector {
class BGeigieConnector : public Worker<Reading> {
public:
explicit BGeigieConnector(Stream& _serial_connection);
virtual ~BGeigieConnector() = default;

/**
* Get a reading from serial
* @param out: output for the reading
* @return: true if a reading was read
*/
bool get_reading(Reading& out);
private:
int8_t produce_data() override;

private:
Stream& _serial_connection;
Expand Down
Loading

0 comments on commit 6703c02

Please sign in to comment.