Skip to content
This repository was archived by the owner on Mar 17, 2025. It is now read-only.

Add main class for Firething and example. #234

Merged
merged 7 commits into from
Dec 9, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

This file was deleted.

43 changes: 43 additions & 0 deletions examples/Firething_ESP8266/Firething_ESP8266.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
//
// Copyright 2016 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

// FirethingDemo_ESP8266 is a sample that demos operation of the firething
// portion of this library. This is a firmware for the esp that acts as
// a bridge between pins on the esp and a firebase database. This includes
// a captive configuration portal.


#include <ESP8266WiFi.h>
#include <Thing.h>

// No config variables.
// Everything is handled through portal.

thing::FireThing fire_thing;

void setup() {
Serial.begin(9600);
Serial.println("Firething starting up...");
fire_thing.SetDebugHandler([](const char* message) { Serial.println(message); });
fire_thing.Setup();
}

void loop() {
fire_thing.Loop();

Serial.println(".");
delay(250);
}
1 change: 1 addition & 0 deletions src/Thing.h
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#include "thing/FireThing.h"
#include "thing/Transcriber.h"
#include "thing/Portal.h"
#include "thing/WiFiManager.h"
48 changes: 48 additions & 0 deletions src/thing/Config.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#include "Arduino.h"
#include "thing/Config.h"
#include "third-party/arduino-json-5.6.7/include/ArduinoJson.h"

namespace thing {

void Config::SerializeToJson(Stream* output, std::function<void(int size)> handle_size) const {
DynamicJsonBuffer jsonBuffer;
JsonObject& root = jsonBuffer.createObject();
root["host"] = host.c_str();
root["auth"] = auth.c_str();
root["path"] = path.c_str();
root["wifi_ssid"] = wifi_ssid.c_str();
root["wifi_key"] = wifi_key.c_str();
root["analog_activation"] = analog_activation_threshold;
root["wifi_connect_attempts"] = wifi_connect_attempts;

JsonObject& pins_root = root.createNestedObject("pins");
pins_root["digital_in"] = pins.digital_in;
pins_root["digital_out"] = pins.digital_out;
pins_root["analog_in"] = pins.analog_in;
pins_root["analog_out"] = pins.analog_out;
pins_root["config_mode_button"] = pins.config_mode_button;

handle_size(root.measureLength());
root.printTo(*output);
}

void Config::ReadFromJson(char* string) {
DynamicJsonBuffer jsonBuffer;
JsonObject& root = jsonBuffer.parseObject(string);
host = root["host"].asString();
auth = root["auth"].asString();
path = root["path"].asString();
wifi_ssid = root["wifi_ssid"].asString();
wifi_key = root["wifi_key"].asString();
analog_activation_threshold = root["activation_threshold"];
wifi_connect_attempts = root["wifi_connect_attempts"];

pins.digital_in = root["pins"]["digital_in"];
pins.digital_out = root["pins"]["digital_out"];
pins.analog_in = root["pins"]["analog_in"];
pins.analog_out = root["pins"]["analog_out"];
pins.config_mode_button = root["pins"]["config_mode_button"];
}

};

23 changes: 19 additions & 4 deletions src/thing/Config.h
Original file line number Diff line number Diff line change
@@ -1,8 +1,20 @@
#ifndef THING_CONFIG_H
#define THING_CONFIG_H

#include "Arduino.h"
#include <string>
#include <functional>

namespace thing {

struct Pins {
int digital_in;
int digital_out;
int analog_in;
int analog_out;
int config_mode_button;
};

struct Config {
std::string host;
std::string auth;
Expand All @@ -14,11 +26,14 @@ struct Config {
// If the change is analog value is less than this amount we don't send an
// update.
float analog_activation_threshold;
int wifi_connect_attempts;

Pins pins;

void SerializeToJson(Stream* output, std::function<void(int size)> handle_size) const;

int pin_digital_in;
int pin_digital_out;
int pin_analog_in;
int pin_analog_out;
// We need a mutable char array here, otherwise a copy will be made.
void ReadFromJson(char* string);
};

} // namespace thing
Expand Down
129 changes: 129 additions & 0 deletions src/thing/FireThing.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
#include "thing/FireThing.h"
#include "Arduino.h"
#include "FS.h"

namespace thing {
namespace {

Config kDefaultConfig = {
"", // firebase host
"", // firebase auth
"/fthing", // path in firebase
"", // wifi ssid
"", // wifi key
0.1, // analog activation threshold
D1, // digital in
BUILTIN_LED, // digital out
A0, // analog in
D1, // analog out
D0, // config mode button
};

const char kStorageFilename[] = "fthing.cfg";

} // namespace

FireThing::FireThing() : debug_([](const char*) {}) {}

bool FireThing::Setup() {
Config config;
if (!ReadConfigFromStorage(&config)) {
debug_("Failed to read config from storage.");
return false;
}
SetPinModes(config);

if (digitalRead(config.pins.config_mode_button) || !ConnectToWiFi(config)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will that only work if you leave config_mode pressed since boot?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

correct you would need to hold the config button on boot to force it into config mode. Or if it can't connect to your wifi network it will go into config mode.

We start the portal either way so if we have some discoverability running and the network supports it you should be able to configure over wifi always.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

here "config mode" only really means running its own wifi network.

wifi_.StartAP();
}

portal_.NotifyOnUpdate([this](const Config& config) {
if (!WriteConfigToStorage(config)) {
debug_("Failed to write config to storage.");
}
SetPinModes(config);
transcriber_.UpdateConfig(config);
ConnectToWiFi(config);
});
portal_.Start(config);
}

void FireThing::Loop() {
wifi_.Loop();
portal_.Loop();
transcriber_.Loop();
}

bool FireThing::ConnectToWiFi(const Config& config) {
debug_("Connecting to wifi:");
debug_(config.wifi_ssid.c_str());
debug_(config.wifi_key.c_str());
if (wifi_.Connect(config.wifi_ssid, config.wifi_key)) {
debug_("Connected");
return true;
}
debug_("Failed to Connect.");
return false;
}

void FireThing::SetPinModes(const Config& config) {
pinMode(config.pins.digital_in, INPUT);
pinMode(config.pins.digital_out, OUTPUT);
pinMode(config.pins.analog_in, INPUT);
pinMode(config.pins.analog_out, OUTPUT);

pinMode(config.pins.config_mode_button, INPUT);
}

bool FireThing::ReadConfigFromStorage(Config* config) {
if (!SPIFFS.begin()) {
debug_("Failed to mount FS.");
return false;
}

if (!SPIFFS.exists(kStorageFilename)) {
debug_("Config not found, using default.");
*config = kDefaultConfig;
} else {
File cfg = SPIFFS.open(kStorageFilename, "r");
if (!cfg) {
debug_("Failed to open config for read");
SPIFFS.end();
return false;
}
char buffer[cfg.size()];
cfg.readBytes(buffer, cfg.size());
config->ReadFromJson(buffer);
debug_("Config read from disk.");
}

SPIFFS.end();
return true;
}

bool FireThing::WriteConfigToStorage(const Config& config) {
if (!SPIFFS.begin()) {
debug_("Failed to mount FS.");
return false;
}

File cfg = SPIFFS.open(kStorageFilename, "w");
if (!cfg) {
debug_("Failed to open config for write");
SPIFFS.end();
return false;
}
config.SerializeToJson(&cfg, [](int){});

SPIFFS.end();
return true;
}

void FireThing::SetDebugHandler(std::function<void(const char* message)> debug) {
debug_ = debug;
wifi_.SetDebugHandler(debug);
portal_.SetDebugHandler(debug);
transcriber_.SetDebugHandler(debug);
}

} // namespace thing
38 changes: 38 additions & 0 deletions src/thing/FireThing.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#ifndef THING_FIRETHING_H
#define THING_FIRETHING_H

#include "thing/Config.h"
#include "thing/WiFiManager.h"
#include "thing/Transcriber.h"
#include "thing/Portal.h"

namespace thing {

// Operates the device as a FireThing which manages a connection
// between several pins and a firebase database. The configuration
// will be read from and persisted too flash.
class FireThing {
public:
FireThing();
bool Setup();
void Loop();

void SetDebugHandler(std::function<void(const char* message)> debug);

private:
bool ReadConfigFromStorage(Config* config);
bool WriteConfigToStorage(const Config& config);

bool ConnectToWiFi(const Config& config);
void SetPinModes(const Config& config);

WiFiManager wifi_;
Portal portal_;
Transcriber transcriber_;
std::function<void(const char* message)> debug_;
};

} // namespace thing


#endif // THING_FIRETHING_H
Loading