Skip to content

Commit

Permalink
Merge pull request #86 from sidoh/v1.3.0
Browse files Browse the repository at this point in the history
v1.3.0
  • Loading branch information
sidoh authored Jun 3, 2017
2 parents 82fd24e + e27c3c6 commit 93e2500
Show file tree
Hide file tree
Showing 11 changed files with 218 additions and 28 deletions.
43 changes: 39 additions & 4 deletions data/web/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
<link href="https://gitcdn.github.io/bootstrap-toggle/2.2.2/css/bootstrap-toggle.min.css" rel="stylesheet"/>
<link href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-slider/9.7.0/css/bootstrap-slider.min.css" rel="stylesheet"/>
<link href="https://cdnjs.cloudflare.com/ajax/libs/selectize.js/0.12.4/css/selectize.bootstrap3.min.css" rel="stylesheet"/>

<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!--[if lt IE 9]>
<script src="https://cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv.js"></script>
<![endif]-->
Expand Down Expand Up @@ -124,8 +124,8 @@
<script lang="text/javascript">
var FORM_SETTINGS = [
"admin_username", "admin_password", "ce_pin", "csn_pin", "reset_pin","packet_repeats",
"http_repeat_factor", "auto_restart_period", "mqtt_server", "mqtt_topic_pattern",
"mqtt_username", "mqtt_password", "radio_interface_type"
"http_repeat_factor", "auto_restart_period", "discovery_port", "mqtt_server",
"mqtt_topic_pattern", "mqtt_username", "mqtt_password", "radio_interface_type"
];

var FORM_SETTINGS_HELP = {
Expand All @@ -141,7 +141,9 @@
mqtt_server : "Domain or IP address of MQTT broker. Optionally specify a port " +
"with (example) mymqqtbroker.com:1884.",
mqtt_topic_pattern : "Pattern for MQTT topics to listen on. Example: " +
"lights/:device_id/:type/:group. See README for further details."
"lights/:device_id/:type/:group. See README for further details.",
discovery_port : "UDP port to listen for discovery packets on. Defaults to " +
"the same port used by MiLight devices, 48899. Use 0 to disable."
}

var UDP_PROTOCOL_VERSIONS = [ 5, 6 ];
Expand Down Expand Up @@ -721,6 +723,29 @@ <h4>Latest Version</h4>
</div>
</div>

<div id="restore-settings-modal" class="modal fade" role="dialog">
<div class="modal-dialog">
<!-- Modal content-->
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">&times;</button>
<h2 class="modal-title">Restore Settings</h2>
</div>
<div class="modal-body">
<form action="/settings" method="post" enctype="multipart/form-data">
<input type="file" name="file"/>
<p>&nbsp;</p>
<input type="submit" name="submit" class="btn btn-success"/>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>

</div>
</div>

<div class="container">
<div class="row header-row">
<div class="col-sm-12">
Expand Down Expand Up @@ -1016,13 +1041,23 @@ <h1>Admin</h1>
Restart
</button>

<button type="button" class="btn btn-danger system-btn" data-command="clear_wifi_config">
Clear Wifi Config
</button>

<button type="button" id="updates-btn" class="btn btn-primary">
Check for Updates
</button>

<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#update-firmware-modal">
Update Firmware
</button>

<a href="/settings" download="settings.json" class="btn btn-primary">Backup Settings</a>

<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#restore-settings-modal">
Restore Settings
</button>
</div>
</div>
</div>
Expand Down
33 changes: 23 additions & 10 deletions lib/MiLight/MiLightClient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -222,17 +222,11 @@ void MiLightClient::command(uint8_t command, uint8_t arg) {
}

void MiLightClient::update(const JsonObject& request) {
if (request.containsKey("status") || request.containsKey("state")) {
String strStatus;
const uint8_t parsedStatus = this->parseStatus(request);

if (request.containsKey("status")) {
strStatus = request.get<char*>("status");
} else {
strStatus = request.get<char*>("state");
}

MiLightStatus status = (strStatus.equalsIgnoreCase("on") || strStatus.equalsIgnoreCase("true")) ? ON : OFF;
this->updateStatus(status);
// Always turn on first
if (parsedStatus == ON) {
this->updateStatus(ON);
}

if (request.containsKey("command")) {
Expand Down Expand Up @@ -308,6 +302,11 @@ void MiLightClient::update(const JsonObject& request) {
if (request.containsKey("mode")) {
this->updateMode(request["mode"]);
}

// Always turn off last
if (parsedStatus == OFF) {
this->updateStatus(OFF);
}
}

void MiLightClient::handleCommand(const String& command) {
Expand Down Expand Up @@ -338,6 +337,20 @@ void MiLightClient::handleCommand(const String& command) {
}
}

uint8_t MiLightClient::parseStatus(const JsonObject& object) {
String strStatus;

if (object.containsKey("status")) {
strStatus = object.get<char*>("status");
} else if (object.containsKey("state")) {
strStatus = object.get<char*>("state");
} else {
return 255;
}

return (strStatus.equalsIgnoreCase("on") || strStatus.equalsIgnoreCase("true")) ? ON : OFF;
}

void MiLightClient::formatPacket(uint8_t* packet, char* buffer) {
formatter->format(packet, buffer);
}
Expand Down
1 change: 1 addition & 0 deletions lib/MiLight/MiLightClient.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ class MiLightClient {
unsigned int resendCount;

MiLightRadio* switchRadio(const MiLightRadioType type);
uint8_t parseStatus(const JsonObject& object);

void flushPacket();
};
Expand Down
2 changes: 2 additions & 0 deletions lib/Settings/Settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ void Settings::patch(JsonObject& parsedSettings) {
this->setIfPresent(parsedSettings, "mqtt_username", mqttUsername);
this->setIfPresent(parsedSettings, "mqtt_password", mqttPassword);
this->setIfPresent(parsedSettings, "mqtt_topic_pattern", mqttTopicPattern);
this->setIfPresent(parsedSettings, "discovery_port", discoveryPort);

if (parsedSettings.containsKey("radio_interface_type")) {
this->radioInterfaceType = Settings::typeFromString(parsedSettings["radio_interface_type"]);
Expand Down Expand Up @@ -139,6 +140,7 @@ void Settings::serialize(Stream& stream, const bool prettyPrint) {
root["mqtt_username"] = this->mqttUsername;
root["mqtt_password"] = this->mqttPassword;
root["mqtt_topic_pattern"] = this->mqttTopicPattern;
root["discovery_port"] = this->discoveryPort;

if (this->deviceIds) {
JsonArray& arr = jsonBuffer.createArray();
Expand Down
4 changes: 3 additions & 1 deletion lib/Settings/Settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,8 @@ class Settings {
numGatewayConfigs(0),
packetRepeats(10),
httpRepeatFactor(5),
_autoRestartPeriod(0)
_autoRestartPeriod(0),
discoveryPort(48899)
{ }

~Settings() {
Expand Down Expand Up @@ -106,6 +107,7 @@ class Settings {
String mqttUsername;
String mqttPassword;
String mqttTopicPattern;
uint16_t discoveryPort;

protected:
size_t _autoRestartPeriod;
Expand Down
85 changes: 85 additions & 0 deletions lib/Udp/MiLightDiscoveryServer.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
#include <MiLightDiscoveryServer.h>
#include <Size.h>
#include <ESP8266WiFi.h>

const char V3_SEARCH_STRING[] = "Link_Wi-Fi";
const char V6_SEARCH_STRING[] = "HF-A11ASSISTHREAD";

MiLightDiscoveryServer::MiLightDiscoveryServer(Settings& settings)
: settings(settings)
{ }

MiLightDiscoveryServer::MiLightDiscoveryServer(MiLightDiscoveryServer& other)
: settings(other.settings)
{ }

MiLightDiscoveryServer& MiLightDiscoveryServer::operator=(MiLightDiscoveryServer other) {
this->settings = other.settings;
this->socket = other.socket;
}

MiLightDiscoveryServer::~MiLightDiscoveryServer() {
socket.stop();
}

void MiLightDiscoveryServer::begin() {
socket.begin(settings.discoveryPort);
}

void MiLightDiscoveryServer::handleClient() {
size_t packetSize = socket.parsePacket();

if (packetSize) {
char buffer[size(V6_SEARCH_STRING) + 1];
socket.read(buffer, packetSize);
buffer[packetSize] = 0;

#ifdef MILIGHT_UDP_DEBUG
printf("Got discovery packet: %s\n", buffer);
#endif

if (strcmp(buffer, V3_SEARCH_STRING) == 0) {
handleDiscovery(5);
} else if (strcmp(buffer, V6_SEARCH_STRING) == 0) {
handleDiscovery(6);
}
}
}

void MiLightDiscoveryServer::handleDiscovery(uint8_t version) {
#ifdef MILIGHT_UDP_DEBUG
printf("Handling discovery for version: %u, %d configs to consider\n", version, settings.numGatewayConfigs);
#endif

char buffer[40];

for (size_t i = 0; i < settings.numGatewayConfigs; i++) {
GatewayConfig* config = settings.gatewayConfigs[i];

if (config->protocolVersion != version) {
continue;
}

IPAddress addr = WiFi.localIP();
char* ptr = buffer;
ptr += sprintf_P(
buffer,
PSTR("%d.%d.%d.%d,00000000%02X%02X"),
addr[0], addr[1], addr[2], addr[3],
(config->deviceId >> 8), (config->deviceId & 0xFF)
);

if (config->protocolVersion == 5) {
sendResponse(buffer);
} else {
sprintf_P(ptr, PSTR(",HF-LPB100"));
sendResponse(buffer);
}
}
}

void MiLightDiscoveryServer::sendResponse(char* buffer) {
socket.beginPacket(socket.remoteIP(), socket.remotePort());
socket.write(buffer);
socket.endPacket();
}
25 changes: 25 additions & 0 deletions lib/Udp/MiLightDiscoveryServer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#include <WiFiUdp.h>
#include <Settings.h>

#ifndef MILIGHT_DISCOVERY_SERVER_H
#define MILIGHT_DISCOVERY_SERVER_H

class MiLightDiscoveryServer {
public:
MiLightDiscoveryServer(Settings& settings);
MiLightDiscoveryServer(MiLightDiscoveryServer&);
MiLightDiscoveryServer& operator=(MiLightDiscoveryServer other);
~MiLightDiscoveryServer();

void begin();
void handleClient();

private:
Settings& settings;
WiFiUDP socket;

void handleDiscovery(uint8_t version);
void sendResponse(char* buffer);
};

#endif
12 changes: 6 additions & 6 deletions lib/Udp/MiLightUdpServer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
#include <ESP8266WiFi.h>

MiLightUdpServer::MiLightUdpServer(MiLightClient*& client, uint16_t port, uint16_t deviceId)
: client(client),
: client(client),
port(port),
deviceId(deviceId),
lastGroup(0)
Expand All @@ -24,18 +24,18 @@ void MiLightUdpServer::stop() {

void MiLightUdpServer::handleClient() {
const size_t packetSize = socket.parsePacket();

if (packetSize) {
socket.read(packetBuffer, packetSize);

#ifdef MILIGHT_UDP_DEBUG
printf("[MiLightUdpServer port %d] - Handling packet: ", port);
for (size_t i = 0; i < packetSize; i++) {
printf("%02X ", packetBuffer[i]);
}
printf("\n");
#endif

handlePacket(packetBuffer, packetSize);
}
}
Expand All @@ -46,6 +46,6 @@ MiLightUdpServer* MiLightUdpServer::fromVersion(uint8_t version, MiLightClient*&
} else if (version == 6) {
return new V6MiLightUdpServer(client, port, deviceId);
}

return NULL;
}
}
16 changes: 14 additions & 2 deletions lib/WebServer/MiLightHttpServer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ void MiLightHttpServer::begin() {
server.on("/", HTTP_GET, handleServeFile(WEB_INDEX_FILENAME, "text/html", DEFAULT_INDEX_PAGE));
server.on("/settings", HTTP_GET, handleServeFile(SETTINGS_FILE, APPLICATION_JSON));
server.on("/settings", HTTP_PUT, [this]() { handleUpdateSettings(); });
server.on("/settings", HTTP_POST, [this]() { server.send(200, TEXT_PLAIN, "success"); }, handleUpdateFile(SETTINGS_FILE));
server.on("/settings", HTTP_POST, [this]() { server.send_P(200, TEXT_PLAIN, PSTR("success. rebooting")); ESP.restart(); }, handleUpdateFile(SETTINGS_FILE));
server.on("/radio_configs", HTTP_GET, [this]() { handleGetRadioConfigs(); });
server.onPattern("/gateway_traffic/:type", HTTP_GET, [this](const UrlTokenBindings* b) { handleListenGateway(b); });
server.onPattern("/gateways/:device_id/:type/:group_id", HTTP_ANY, [this](const UrlTokenBindings* b) { handleUpdateGroup(b); });
Expand Down Expand Up @@ -128,7 +128,19 @@ void MiLightHttpServer::handleSystemPost() {
delay(100);

ESP.restart();
}

handled = true;
} else if (request["command"] == "clear_wifi_config") {
Serial.println(F("Resetting Wifi and then Restarting..."));
server.send(200, TEXT_PLAIN, "true");

delay(100);
ESP.eraseConfig();
delay(100);
ESP.restart();

handled = true;
}
}

if (handled) {
Expand Down
2 changes: 1 addition & 1 deletion platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ lib_deps_external =
ArduinoJson
PubSubClient
https://github.com/ratkins/RGBConverter
build_flags = !python .get_version.py
build_flags = !python .get_version.py -D MILIGHT_UDP_DEBUG
# -D MQTT_DEBUG
# -D MILIGHT_UDP_DEBUG
# -D DEBUG_PRINTF
Expand Down
Loading

0 comments on commit 93e2500

Please sign in to comment.