diff options
author | Trygve Laugstøl <trygvis@inamo.no> | 2016-03-13 11:10:51 +0100 |
---|---|---|
committer | Trygve Laugstøl <trygvis@inamo.no> | 2016-03-13 11:10:51 +0100 |
commit | 1effc988e95a7c39ed673bbcc840ff20cec4bb75 (patch) | |
tree | 33590ebdc9bf2263b18824329c8c522121ec3d62 /src/impl | |
download | diller-1effc988e95a7c39ed673bbcc840ff20cec4bb75.tar.gz diller-1effc988e95a7c39ed673bbcc840ff20cec4bb75.tar.bz2 diller-1effc988e95a7c39ed673bbcc840ff20cec4bb75.tar.xz diller-1effc988e95a7c39ed673bbcc840ff20cec4bb75.zip |
o Initial import of Diller Arduino library.
Diffstat (limited to 'src/impl')
-rw-r--r-- | src/impl/diller_core_impl.h | 150 | ||||
-rw-r--r-- | src/impl/diller_serial_impl.h | 183 |
2 files changed, 333 insertions, 0 deletions
diff --git a/src/impl/diller_core_impl.h b/src/impl/diller_core_impl.h new file mode 100644 index 0000000..1246e59 --- /dev/null +++ b/src/impl/diller_core_impl.h @@ -0,0 +1,150 @@ +#include <Arduino.h> +#include <ESP8266WiFi.h> +#include <PubSubClient.h> + +extern WiFiClient wifi_client; +extern PubSubClient mqtt_client; + +namespace diller { +namespace core { + +using diller::utils::tty_status; +using diller::utils::property; + +// core::core + +template<uint8_t number_of_properties> +core<number_of_properties>::core(const String &mqtt_host, int mqtt_port) : + mqtt_host(mqtt_host), mqtt_port(mqtt_port), property_action_listener_(nullptr) { + mac = WiFi.macAddress(); + mac.toLowerCase(); + client_id = "diller-" + mac; +} + +template<uint8_t number_of_properties> +void core<number_of_properties>::callback(char* topic_, byte* payload, unsigned int length) { + Serial.print("got message on "); + Serial.println(topic_); + Serial.println("payload"); + Serial.write(payload, length); + Serial.println(); + + String prefix = "/diller/" + mac + "/property/"; + String topic(topic_); + if (!topic.startsWith(prefix)) { + Serial.print("debug bad-prefix: "); + Serial.println(topic); + return; + } + + topic.remove(0, prefix.length()); + property *p = nullptr; + for (auto i = 0; i < properties.size(); i++) { + auto *x = properties[i]; + if (topic.startsWith(x->id())) { + p = x; + break; + } + } + + if (p) { + topic.remove(0, p->id().length() + 1); + + Serial.print("debug property="); + Serial.print(p->id()); + Serial.print(", topic="); + Serial.println(topic); + + property_action a; + + if (topic == "value") { + Serial.println("debug action=value"); + a = property_action::VALUE; + } else if (topic == "name") { + Serial.println("debug action=name"); + a = property_action::NAME; + } else if (topic == "description") { + Serial.println("debug action=description"); + a = property_action::DESCRIPTION; + } else { + return; + } + + if (property_action_listener_) { + property_action_listener_->on_property_action(p, a); + } + } else { + Serial.print("debug unknown-property"); + } +} + +template<uint8_t number_of_properties> +bool core<number_of_properties>::connected() const { + return mqtt_client.connected(); +} + +template<uint8_t number_of_properties> +void core<number_of_properties>::setup() { + mqtt_client.setServer(mqtt_host.c_str(), mqtt_port); + mqtt_client.setCallback([this](char* topic_, byte* payload, unsigned int length) { + callback(topic_, payload, length); + }); +} + +template<uint8_t number_of_properties> +void core<number_of_properties>::loop() { + auto wl_status = WiFi.status(); + + if (wl_status == WL_CONNECTED) { + if (!mqtt_client.loop()) { + Serial.println("status mqtt=connecting"); + if (mqtt_client.connect(client_id.c_str())) { + Serial.println("status mqtt=connected"); + } else { + Serial.println("status mqtt=disconnected"); + } + } + } +} + +template<uint8_t number_of_properties> +diller_error core<number_of_properties>::cmd_property(const char *id, const char *value, const char *name) { + if (!id) { + return diller_error::INVAL; + } + + auto p = properties.find(id); + + if (!p) { + return diller_error::NOMEM; + } + + if (value) { + String topic = "/diller/" + mac + "/property/" + id + "/value"; + mqtt_client.publish(topic.c_str(), value); + } + + if (name) { + String topic = "/diller/" + mac + "/property/" + id + "/name"; + mqtt_client.publish(topic.c_str(), name); + } + + if (p->is_new()) { + String topic = "/diller/" + mac + "/property/" + id + "/#"; + mqtt_client.subscribe(topic.c_str()); + Serial.print("debug subscribing="); + Serial.println(topic); + + p->set_old(); + } + + return diller_error::OK; +} + +template<uint8_t number_of_properties> +void core<number_of_properties>::set_property_action_listener(property_action_listener *l) { + this->property_action_listener_ = l; +} + +} // namespace core +} // namespace diller diff --git a/src/impl/diller_serial_impl.h b/src/impl/diller_serial_impl.h new file mode 100644 index 0000000..47c18b5 --- /dev/null +++ b/src/impl/diller_serial_impl.h @@ -0,0 +1,183 @@ +// #include <Arduino.h> +#include <ESP8266WiFi.h> +// #include <PubSubClient.h> + +extern WiFiClient wifi_client; +extern PubSubClient mqtt_client; + +namespace diller { +namespace serial { + +using diller::utils::tty_status; + +template<typename d_core, typename io_t> +void diller_serial<d_core, io_t>::cmd_network() { + Serial.print("ok ip="); + WiFi.localIP().printTo(Serial); + Serial.print(" gateway="); + WiFi.gatewayIP().printTo(Serial); + Serial.print(" netmask="); + WiFi.subnetMask().printTo(Serial); + Serial.println(); +} + +template<typename d_core, typename io_t> +void diller_serial<d_core, io_t>::cmd_wlan() { + Serial.print("ok ssid="); + tty.quote(WiFi.SSID()); + if (send_wlan_password) { + Serial.print(" password="); + Serial.print(WiFi.psk()); + } + + Serial.print(" mac="); + Serial.println(diller.mac); +} + +template<typename d_core, typename io_t> +void diller_serial<d_core, io_t>::cmd_wlan(const char* ssid, const char* password) { + WiFi.begin(ssid, password); + Serial.println("ok"); +} + +template<typename d_core, typename io_t> +void diller_serial<d_core, io_t>::cmd_property(const char *id, const char *value, const char *name) { + auto ret = diller.cmd_property(id, value, name); + + if (ret != diller_error::OK) { + Serial.print("fail error="); + Serial.println(to_string(ret)); + } +} + +template<typename d_core, typename io_t> +void diller_serial<d_core, io_t>::cmd_list_properties() { + Serial.print("ok count="); + Serial.println(diller.properties.size()); + for (auto i = 0; i < diller.properties.size(); i++) { + auto p = diller.properties[i]; + Serial.print("property id="); + Serial.print(p->id()); + Serial.print(" name="); + Serial.print(p->name()); + Serial.print(" description="); + Serial.print(p->description()); + Serial.println(); + } +} + +template<typename d_core, typename io_t> +void diller_serial<d_core, io_t>::show_status(wl_status_t wl_status) { + const char *wl_status_s; + if (wl_status == WL_IDLE_STATUS) { + wl_status_s = "idle"; + } else if (wl_status == WL_NO_SSID_AVAIL) { + wl_status_s = "no-ssid"; + } else if (wl_status == WL_SCAN_COMPLETED) { + wl_status_s = "scan-completed"; + } else if (wl_status == WL_CONNECTED) { + wl_status_s = "connected"; + } else if (wl_status == WL_CONNECT_FAILED) { + wl_status_s = "connect-failed"; + } else if (wl_status == WL_CONNECTION_LOST) { + wl_status_s = "connection-lost"; + } else if (wl_status == WL_DISCONNECTED) { + wl_status_s = "disconnected"; + } else { + wl_status_s = "unknown"; + } + + const char *mqtt_status_s; + if (diller.connected()) { + mqtt_status_s = "connected"; + } else { + mqtt_status_s = "disconnected"; + } + + Serial.print("status wlan="); + Serial.print(wl_status_s); + Serial.print(" mqtt="); + Serial.println(mqtt_status_s); +} + +template<typename d_core, typename io_t> +void diller_serial<d_core, io_t>::process_command() { + if (params.is_empty()) { + return; + } + + auto cmd = params.key(0); + + if (strcmp("network", cmd) == 0) { + if (params.size() == 1) { + cmd_network(); + } else { + Serial.println("fail error=invalid_argument"); + } + } else if (strcmp("wlan", cmd) == 0) { + if (params.size() == 1) { + cmd_wlan(); + } else if (params.size() == 3) { + const char* ssid = params.find("ssid"); + const char* password = params.find("password"); + cmd_wlan(ssid, password); + } else { + Serial.println("fail error=invalid_argument"); + } + } else if (strcmp("property", cmd) == 0) { + auto id = params.find("id"); + auto value = params.find("value"); + auto name = params.find("name"); + cmd_property(id, value, name); + } else if (strcmp("list-properties", cmd) == 0) { + cmd_list_properties(); + } else { + Serial.print("fail error=unknown_command cmd="); + tty.escape(cmd); + Serial.println(); + } +} + +template<typename d_core, typename io_t> +void diller_serial<d_core, io_t>::setup() { + diller.set_property_action_listener(this); +} + +template<typename d_core, typename io_t> +void diller_serial<d_core, io_t>::loop() { + if (tty.readline() == tty_status::FULL_LINE) { + diller_parser.parse(tty.line); + + process_command(); + } + + static auto last_wl_status = WiFi.status(); + auto wl_status = WiFi.status(); + + static auto last_status = millis(); + auto now = millis(); + static const auto show_status_interval = 5000; + + if (last_wl_status != wl_status) { + show_status(wl_status); + last_wl_status = wl_status; + last_status = now; + } else if (now > (last_status + show_status_interval)) { + show_status(wl_status); + last_status = now; + } +} + +template<typename d_core, typename io_t> +void diller_serial<d_core, io_t>::on_property_action(const property *p, property_action) { + Serial.print("property id="); + tty.quote(p->id()); + Serial.print(" value="); + tty.quote(p->value()); + Serial.print(" description="); + tty.quote(p->description()); + Serial.println(); +} + +} // namespace serial +} // namespace diller |