mirror of
https://github.com/esphome/esphome.git
synced 2024-11-21 22:48:10 +01:00
Add clean MQTT button to dashboard (#139)
This commit is contained in:
parent
12f20fc3cf
commit
ef54e33b70
4 changed files with 87 additions and 4 deletions
|
@ -451,6 +451,8 @@ def parse_args(argv):
|
||||||
default=6052)
|
default=6052)
|
||||||
dashboard.add_argument("--password", help="The optional password to require for all requests.",
|
dashboard.add_argument("--password", help="The optional password to require for all requests.",
|
||||||
type=str, default='')
|
type=str, default='')
|
||||||
|
dashboard.add_argument("--open-ui", help="Open the dashboard UI in a browser.",
|
||||||
|
action='store_true')
|
||||||
|
|
||||||
return parser.parse_args(argv[1:])
|
return parser.parse_args(argv[1:])
|
||||||
|
|
||||||
|
|
|
@ -117,6 +117,13 @@ class EsphomeyamlValidateHandler(EsphomeyamlCommandWebSocket):
|
||||||
return ["esphomeyaml", config_file, "config"]
|
return ["esphomeyaml", config_file, "config"]
|
||||||
|
|
||||||
|
|
||||||
|
class EsphomeyamlCleanMqttHandler(EsphomeyamlCommandWebSocket):
|
||||||
|
def build_command(self, message):
|
||||||
|
js = json.loads(message)
|
||||||
|
config_file = os.path.join(CONFIG_DIR, js['configuration'])
|
||||||
|
return ["esphomeyaml", config_file, "clean-mqtt"]
|
||||||
|
|
||||||
|
|
||||||
class SerialPortRequestHandler(BaseHandler):
|
class SerialPortRequestHandler(BaseHandler):
|
||||||
def get(self):
|
def get(self):
|
||||||
if not self.is_authenticated():
|
if not self.is_authenticated():
|
||||||
|
@ -213,6 +220,7 @@ def make_app(debug=False):
|
||||||
(r"/run", EsphomeyamlRunHandler),
|
(r"/run", EsphomeyamlRunHandler),
|
||||||
(r"/compile", EsphomeyamlCompileHandler),
|
(r"/compile", EsphomeyamlCompileHandler),
|
||||||
(r"/validate", EsphomeyamlValidateHandler),
|
(r"/validate", EsphomeyamlValidateHandler),
|
||||||
|
(r"/clean-mqtt", EsphomeyamlCleanMqttHandler),
|
||||||
(r"/download.bin", DownloadBinaryRequestHandler),
|
(r"/download.bin", DownloadBinaryRequestHandler),
|
||||||
(r"/serial-ports", SerialPortRequestHandler),
|
(r"/serial-ports", SerialPortRequestHandler),
|
||||||
(r"/wizard.html", WizardRequestHandler),
|
(r"/wizard.html", WizardRequestHandler),
|
||||||
|
@ -251,6 +259,12 @@ def start_web_server(args):
|
||||||
args.port, CONFIG_DIR)
|
args.port, CONFIG_DIR)
|
||||||
app = make_app(args.verbose)
|
app = make_app(args.verbose)
|
||||||
app.listen(args.port)
|
app.listen(args.port)
|
||||||
|
|
||||||
|
if args.open_ui:
|
||||||
|
import webbrowser
|
||||||
|
|
||||||
|
webbrowser.open('localhost:{}'.format(args.port))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
tornado.ioloop.IOLoop.current().start()
|
tornado.ioloop.IOLoop.current().start()
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
|
|
|
@ -159,6 +159,10 @@
|
||||||
margin-right: 24px;
|
margin-right: 24px;
|
||||||
width: 350px;
|
width: 350px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.dropdown-trigger {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||||||
|
@ -191,7 +195,7 @@
|
||||||
|
|
||||||
<main>
|
<main>
|
||||||
<div class="container">
|
<div class="container">
|
||||||
{% for file, full_path in zip(files, full_path_files) %}
|
{% for i, (file, full_path) in enumerate(zip(files, full_path_files)) %}
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col s8 offset-s2 m10 offset-m1 l12">
|
<div class="col s8 offset-s2 m10 offset-m1 l12">
|
||||||
<div class="card horizontal">
|
<div class="card horizontal">
|
||||||
|
@ -200,7 +204,10 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="card-stacked">
|
<div class="card-stacked">
|
||||||
<div class="card-content">
|
<div class="card-content">
|
||||||
<span class="card-title">{{ escape(file) }}</span>
|
<span class="card-title">
|
||||||
|
{{ escape(file) }}
|
||||||
|
<i class="material-icons right dropdown-trigger" data-target="dropdown-{{ i }}">more_vert</i>
|
||||||
|
</span>
|
||||||
<p>
|
<p>
|
||||||
Full path: <code class="inlinecode">{{ escape(full_path) }}</code>
|
Full path: <code class="inlinecode">{{ escape(full_path) }}</code>
|
||||||
</p>
|
</p>
|
||||||
|
@ -211,6 +218,9 @@
|
||||||
<a href="#" class="action-show-logs" data-node="{{ file }}">Show Logs</a>
|
<a href="#" class="action-show-logs" data-node="{{ file }}">Show Logs</a>
|
||||||
<a href="#" class="action-validate" data-node="{{ file }}">Validate</a>
|
<a href="#" class="action-validate" data-node="{{ file }}">Validate</a>
|
||||||
</div>
|
</div>
|
||||||
|
<ul id="dropdown-{{ i }}" class="dropdown-content">
|
||||||
|
<li><a href="#" class="action-clean-mqtt" data-node="{{ file }}">Clean MQTT</a></li>
|
||||||
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -462,6 +472,18 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div id="modal-clean-mqtt" class="modal modal-fixed-footer">
|
||||||
|
<div class="modal-content">
|
||||||
|
<h4>Clean MQTT discovery <code class="inlinecode filename"></code></h4>
|
||||||
|
<div class="log-container">
|
||||||
|
<pre class="log"></pre>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<a class="modal-close waves-effect waves-green btn-flat stop-logs">Stop</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<a class="btn-floating btn-large ribbon-fab waves-effect waves-light pink accent-2" id="setup-wizard-start">
|
<a class="btn-floating btn-large ribbon-fab waves-effect waves-light pink accent-2" id="setup-wizard-start">
|
||||||
<i class="material-icons">add</i>
|
<i class="material-icons">add</i>
|
||||||
</a>
|
</a>
|
||||||
|
@ -539,6 +561,7 @@
|
||||||
if (allEqual)
|
if (allEqual)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
const hasNewPort = response.length >= ports.length;
|
||||||
|
|
||||||
ports = response;
|
ports = response;
|
||||||
|
|
||||||
|
@ -559,7 +582,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
M.FormSelect.init(portSelect, {});
|
M.FormSelect.init(portSelect, {});
|
||||||
if (!begin)
|
if (!begin && hasNewPort)
|
||||||
M.toast({html: "Discovered new serial port."});
|
M.toast({html: "Discovered new serial port."});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -784,6 +807,48 @@
|
||||||
link.click();
|
link.click();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const cleanMqttModalElem = document.getElementById("modal-clean-mqtt");
|
||||||
|
|
||||||
|
document.querySelectorAll(".action-clean-mqtt").forEach((btn) => {
|
||||||
|
btn.addEventListener('click', (e) => {
|
||||||
|
configuration = e.target.getAttribute('data-node');
|
||||||
|
const modalInstance = M.Modal.getInstance(cleanMqttModalElem);
|
||||||
|
const log = cleanMqttModalElem.querySelector(".log");
|
||||||
|
log.innerHTML = "";
|
||||||
|
const stopLogsButton = cleanMqttModalElem.querySelector(".stop-logs");
|
||||||
|
let stopped = false;
|
||||||
|
stopLogsButton.innerHTML = "Stop";
|
||||||
|
modalInstance.open();
|
||||||
|
|
||||||
|
const filenameField = cleanMqttModalElem.querySelector('.filename');
|
||||||
|
filenameField.innerHTML = configuration;
|
||||||
|
|
||||||
|
const logSocket = new WebSocket(wsUrl + "/clean-mqtt");
|
||||||
|
logSocket.addEventListener('message', (event) => {
|
||||||
|
const data = JSON.parse(event.data);
|
||||||
|
if (data.event === "line") {
|
||||||
|
const msg = data.data;
|
||||||
|
log.innerHTML += colorReplace(msg);
|
||||||
|
} else if (data.event === "exit") {
|
||||||
|
stopLogsButton.innerHTML = "Close";
|
||||||
|
stopped = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
logSocket.addEventListener('open', () => {
|
||||||
|
const msg = JSON.stringify({configuration: configuration});
|
||||||
|
logSocket.send(msg);
|
||||||
|
});
|
||||||
|
logSocket.addEventListener('close', () => {
|
||||||
|
if (!stopped) {
|
||||||
|
M.toast({html: 'Terminated process.'});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
modalInstance.options.onCloseStart = () => {
|
||||||
|
logSocket.close();
|
||||||
|
};
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
const modalSetupElem = document.getElementById("modal-wizard");
|
const modalSetupElem = document.getElementById("modal-wizard");
|
||||||
const setupWizardStart = document.getElementById('setup-wizard-start');
|
const setupWizardStart = document.getElementById('setup-wizard-start');
|
||||||
const startWizard = () => {
|
const startWizard = () => {
|
||||||
|
|
|
@ -83,7 +83,9 @@ def clear_topic(config, topic, username=None, password=None, client_id=None):
|
||||||
discovery_prefix = config[CONF_MQTT].get(CONF_DISCOVERY_PREFIX, u'homeassistant')
|
discovery_prefix = config[CONF_MQTT].get(CONF_DISCOVERY_PREFIX, u'homeassistant')
|
||||||
name = config[CONF_ESPHOMEYAML][CONF_NAME]
|
name = config[CONF_ESPHOMEYAML][CONF_NAME]
|
||||||
topic = u'{}/+/{}/#'.format(discovery_prefix, name)
|
topic = u'{}/+/{}/#'.format(discovery_prefix, name)
|
||||||
_LOGGER.info(u"Clearing messages from %s", topic)
|
_LOGGER.info(u"Clearing messages from '%s'", topic)
|
||||||
|
_LOGGER.info(u"Please close this window when no more messages appear and the "
|
||||||
|
u"MQTT topic has been cleared of retained messages.")
|
||||||
|
|
||||||
def on_message(client, userdata, msg):
|
def on_message(client, userdata, msg):
|
||||||
if not msg.payload or not msg.retain:
|
if not msg.payload or not msg.retain:
|
||||||
|
|
Loading…
Reference in a new issue