mirror of
https://github.com/esphome/esphome.git
synced 2025-03-14 06:38:17 +00:00
Updates
This commit is contained in:
parent
254e0a63c2
commit
b8c55c5043
@ -1,18 +1,19 @@
|
||||
from __future__ import print_function
|
||||
|
||||
import argparse
|
||||
from datetime import datetime
|
||||
import logging
|
||||
import os
|
||||
import random
|
||||
import sys
|
||||
|
||||
from esphomeyaml import core, mqtt, wizard, writer, yaml_util, const
|
||||
from esphomeyaml import const, core, mqtt, wizard, writer, yaml_util
|
||||
from esphomeyaml.config import core_to_code, get_component, iter_components, read_config
|
||||
from esphomeyaml.const import CONF_BAUD_RATE, CONF_DOMAIN, CONF_ESPHOMEYAML, CONF_HOSTNAME, \
|
||||
CONF_LOGGER, CONF_MANUAL_IP, CONF_NAME, CONF_STATIC_IP, CONF_WIFI
|
||||
CONF_LOGGER, CONF_MANUAL_IP, CONF_NAME, CONF_STATIC_IP, CONF_WIFI, ESP_PLATFORM_ESP8266
|
||||
from esphomeyaml.core import ESPHomeYAMLError
|
||||
from esphomeyaml.helpers import AssignmentExpression, RawStatement, _EXPRESSIONS, add, add_task, \
|
||||
color, get_variable, indent, quote, statement, Expression
|
||||
from esphomeyaml.helpers import AssignmentExpression, Expression, RawStatement, _EXPRESSIONS, add, \
|
||||
add_task, color, get_variable, indent, quote, statement
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
@ -66,7 +67,7 @@ def choose_serial_port(config):
|
||||
return result[opt][0]
|
||||
|
||||
|
||||
def run_platformio(*cmd):
|
||||
def run_platformio(*cmd, **kwargs):
|
||||
def mock_exit(return_code):
|
||||
raise SystemExit(return_code)
|
||||
|
||||
@ -75,10 +76,13 @@ def run_platformio(*cmd):
|
||||
full_cmd = u' '.join(quote(x) for x in cmd)
|
||||
_LOGGER.info(u"Running: %s", full_cmd)
|
||||
try:
|
||||
import platformio.__main__
|
||||
main = kwargs.get('main')
|
||||
if main is None:
|
||||
import platformio.__main__
|
||||
main = platformio.__main__.main
|
||||
sys.argv = list(cmd)
|
||||
sys.exit = mock_exit
|
||||
return platformio.__main__.main()
|
||||
return main() or 0
|
||||
except KeyboardInterrupt:
|
||||
return 1
|
||||
except SystemExit as err:
|
||||
@ -91,13 +95,19 @@ def run_platformio(*cmd):
|
||||
sys.exit = orig_exit
|
||||
|
||||
|
||||
def run_miniterm(config, port):
|
||||
from serial.tools import miniterm
|
||||
def run_miniterm(config, port, escape=False):
|
||||
import serial
|
||||
baud_rate = config.get(CONF_LOGGER, {}).get(CONF_BAUD_RATE, 115200)
|
||||
sys.argv = ['miniterm', '--raw', '--exit-char', '3']
|
||||
miniterm.main(
|
||||
default_port=port,
|
||||
default_baudrate=baud_rate)
|
||||
_LOGGER.info("Starting log output from %s with baud rate %s", port, baud_rate)
|
||||
|
||||
with serial.Serial(port, baudrate=baud_rate) as ser:
|
||||
while True:
|
||||
line = ser.readline()
|
||||
time = datetime.now().time().strftime('[%H:%M:%S]')
|
||||
message = time + line.decode('unicode-escape').replace('\r', '').replace('\n', '')
|
||||
if escape:
|
||||
message = message.replace('\033', '\\033').encode('ascii', 'replace')
|
||||
print(message)
|
||||
|
||||
|
||||
def write_cpp(config):
|
||||
@ -162,9 +172,21 @@ def get_upload_host(config):
|
||||
return host
|
||||
|
||||
|
||||
def upload_using_esptool(config, port):
|
||||
import esptool
|
||||
|
||||
name = get_name(config)
|
||||
path = os.path.join(get_base_path(config), '.pioenvs', name, 'firmware.bin')
|
||||
return run_platformio('esptool.py', '--before', 'default_reset', '--after', 'hard_reset',
|
||||
'--chip', 'esp8266', '--port', port, 'write_flash', '0x0',
|
||||
path, main=esptool._main)
|
||||
|
||||
|
||||
def upload_program(config, args, port):
|
||||
_LOGGER.info("Uploading binary...")
|
||||
if port != 'OTA':
|
||||
if core.ESP_PLATFORM == ESP_PLATFORM_ESP8266 and args.use_esptoolpy:
|
||||
return upload_using_esptool(config, port)
|
||||
return run_platformio('platformio', 'run', '-d', get_base_path(config),
|
||||
'-t', 'upload', '--upload-port', port)
|
||||
|
||||
@ -190,7 +212,7 @@ def upload_program(config, args, port):
|
||||
|
||||
def show_logs(config, args, port, escape=False):
|
||||
if port != 'OTA':
|
||||
run_miniterm(config, port)
|
||||
run_miniterm(config, port, escape=escape)
|
||||
return 0
|
||||
return mqtt.show_logs(config, args.topic, args.username, args.password, args.client_id,
|
||||
escape=escape)
|
||||
@ -329,6 +351,9 @@ def parse_args(argv):
|
||||
parser_upload.add_argument('--upload-port', help="Manually specify the upload port to use. "
|
||||
"For example /dev/cu.SLAB_USBtoUART.")
|
||||
parser_upload.add_argument('--host-port', help="Specify the host port.", type=int)
|
||||
parser_upload.add_argument('--use-esptoolpy',
|
||||
help="Use esptool.py for HassIO (only for ESP8266)",
|
||||
action='store_true')
|
||||
|
||||
parser_logs = subparsers.add_parser('logs', help='Validate the configuration '
|
||||
'and show all MQTT logs.')
|
||||
@ -354,6 +379,8 @@ def parse_args(argv):
|
||||
parser_run.add_argument('--client-id', help='Manually set the client id for logs.')
|
||||
parser_run.add_argument('--escape', help="Escape ANSI color codes for HassIO",
|
||||
action='store_true')
|
||||
parser_run.add_argument('--use-esptoolpy', help="Use esptool.py for HassIO (only for ESP8266)",
|
||||
action='store_true')
|
||||
|
||||
parser_clean = subparsers.add_parser('clean-mqtt', help="Helper to clear an MQTT topic from "
|
||||
"retain messages.")
|
||||
@ -408,6 +435,8 @@ def main():
|
||||
except ESPHomeYAMLError as e:
|
||||
_LOGGER.error(e)
|
||||
return 1
|
||||
except KeyboardInterrupt:
|
||||
return 1
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
@ -26,7 +26,7 @@ zero_to_one_float = vol.All(vol.Coerce(float), vol.Range(min=0, max=1))
|
||||
positive_int = vol.All(vol.Coerce(int), vol.Range(min=0))
|
||||
positive_not_null_int = vol.All(vol.Coerce(int), vol.Range(min=0, min_included=False))
|
||||
|
||||
ALLOWED_NAME_CHARS = u'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_'
|
||||
ALLOWED_NAME_CHARS = u'abcdefghijklmnopqrstuvwxyz0123456789_'
|
||||
|
||||
RESERVED_IDS = [
|
||||
# C++ keywords http://en.cppreference.com/w/cpp/keyword
|
||||
|
@ -1,9 +1,9 @@
|
||||
from __future__ import print_function
|
||||
|
||||
import codecs
|
||||
import os
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
import random
|
||||
import subprocess
|
||||
|
||||
@ -19,8 +19,8 @@ try:
|
||||
except ImportError as err:
|
||||
pass
|
||||
|
||||
from esphomeyaml import const
|
||||
from esphomeyaml.__main__ import get_serial_ports
|
||||
from esphomeyaml import const, core, __main__
|
||||
from esphomeyaml.__main__ import get_serial_ports, get_base_path, get_name
|
||||
from esphomeyaml.helpers import quote
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
@ -76,8 +76,9 @@ class EsphomeyamlLogsHandler(EsphomeyamlCommandWebSocket):
|
||||
super(EsphomeyamlLogsHandler, self).__init__(application, request, **kwargs)
|
||||
|
||||
def build_command(self, message):
|
||||
config_file = CONFIG_DIR + '/' + message
|
||||
return ["esphomeyaml", config_file, "logs", '--escape', '--serial-port', 'OTA']
|
||||
js = json.loads(message)
|
||||
config_file = CONFIG_DIR + '/' + js['configuration']
|
||||
return ["esphomeyaml", config_file, "logs", '--serial-port', js["port"], '--escape']
|
||||
|
||||
|
||||
class EsphomeyamlRunHandler(EsphomeyamlCommandWebSocket):
|
||||
@ -86,8 +87,19 @@ class EsphomeyamlRunHandler(EsphomeyamlCommandWebSocket):
|
||||
|
||||
def build_command(self, message):
|
||||
js = json.loads(message)
|
||||
config_file = CONFIG_DIR + '/' + js['configuration']
|
||||
return ["esphomeyaml", config_file, "run", '--upload-port', js["port"], '--escape']
|
||||
config_file = os.path.join(CONFIG_DIR, js['configuration'])
|
||||
return ["esphomeyaml", config_file, "run", '--upload-port', js["port"],
|
||||
'--escape', '--use-esptoolpy']
|
||||
|
||||
|
||||
class EsphomeyamlCompileHandler(EsphomeyamlCommandWebSocket):
|
||||
def __init__(self, application, request, **kwargs):
|
||||
super(EsphomeyamlCompileHandler, self).__init__(application, request, **kwargs)
|
||||
|
||||
def build_command(self, message):
|
||||
js = json.loads(message)
|
||||
config_file = os.path.join(CONFIG_DIR, js['configuration'])
|
||||
return ["esphomeyaml", config_file, "compile"]
|
||||
|
||||
|
||||
class SerialPortRequestHandler(tornado.web.RequestHandler):
|
||||
@ -107,7 +119,7 @@ class WizardRequestHandler(tornado.web.RequestHandler):
|
||||
def post(self):
|
||||
from esphomeyaml import wizard
|
||||
|
||||
kwargs = {k:''.join(v) for k,v in self.request.arguments.iteritems()}
|
||||
kwargs = {k: ''.join(v) for k, v in self.request.arguments.iteritems()}
|
||||
config = wizard.wizard_file(**kwargs)
|
||||
destination = os.path.join(CONFIG_DIR, kwargs['name'] + '.yaml')
|
||||
with codecs.open(destination, 'w') as f_handle:
|
||||
@ -116,10 +128,31 @@ class WizardRequestHandler(tornado.web.RequestHandler):
|
||||
self.redirect('/')
|
||||
|
||||
|
||||
class DownloadBinaryRequestHandler(tornado.web.RequestHandler):
|
||||
def get(self):
|
||||
configuration = self.get_argument('configuration')
|
||||
config_file = os.path.join(CONFIG_DIR, configuration)
|
||||
core.CONFIG_PATH = config_file
|
||||
config = __main__.read_config(core.CONFIG_PATH)
|
||||
name = get_name(config)
|
||||
path = os.path.join(get_base_path(config), '.pioenvs', name, 'firmware.bin')
|
||||
self.set_header('Content-Type', 'application/octet-stream')
|
||||
self.set_header("Content-Disposition", 'attachment; filename="{}.bin"'.format(name))
|
||||
with open(path, 'rb') as f:
|
||||
while 1:
|
||||
data = f.read(16384) # or some other nice-sized chunk
|
||||
if not data:
|
||||
break
|
||||
self.write(data)
|
||||
self.finish()
|
||||
|
||||
|
||||
class MainRequestHandler(tornado.web.RequestHandler):
|
||||
def get(self):
|
||||
files = [f for f in os.listdir(CONFIG_DIR) if f.endswith('.yaml')]
|
||||
self.render("templates/index.html", files=files, version=const.__version__)
|
||||
full_path_files = [os.path.join(CONFIG_DIR, f) for f in files]
|
||||
self.render("templates/index.html", files=files, full_path_files=full_path_files,
|
||||
version=const.__version__)
|
||||
|
||||
|
||||
def make_app():
|
||||
@ -128,15 +161,19 @@ def make_app():
|
||||
(r"/", MainRequestHandler),
|
||||
(r"/logs", EsphomeyamlLogsHandler),
|
||||
(r"/run", EsphomeyamlRunHandler),
|
||||
(r"/compile", EsphomeyamlCompileHandler),
|
||||
(r"/download.bin", DownloadBinaryRequestHandler),
|
||||
(r"/serial-ports", SerialPortRequestHandler),
|
||||
(r"/wizard.html", WizardRequestHandler),
|
||||
(r'/static/(.*)', tornado.web.StaticFileHandler, {'path': static_path}),
|
||||
])
|
||||
], debug=True)
|
||||
|
||||
|
||||
def start_web_server(args):
|
||||
global CONFIG_DIR
|
||||
CONFIG_DIR = args.configuration
|
||||
if not os.path.exists(CONFIG_DIR):
|
||||
os.makedirs(CONFIG_DIR)
|
||||
|
||||
_LOGGER.info("Starting HassIO add-on web server on port %s and configuration dir %s...",
|
||||
args.port, CONFIG_DIR)
|
||||
|
@ -72,6 +72,16 @@
|
||||
color: #DDD;
|
||||
}
|
||||
|
||||
.inlinecode {
|
||||
box-sizing: border-box;
|
||||
padding: 0.2em 0.4em;
|
||||
margin: 0;
|
||||
font-size: 85%;
|
||||
background-color: rgba(27,31,35,0.05);
|
||||
border-radius: 3px;
|
||||
font-family: "SFMono-Regular",Consolas,"Liberation Mono",Menlo,Courier,monospace;
|
||||
}
|
||||
|
||||
.log.bold {
|
||||
font-weight: bold;
|
||||
}
|
||||
@ -112,20 +122,11 @@
|
||||
.modal {
|
||||
width: 90%;
|
||||
max-height: 85%;
|
||||
}
|
||||
|
||||
.log-container {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
width: calc(100% - 48px);
|
||||
height: 80% !important;
|
||||
}
|
||||
|
||||
.log {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
left: 0;
|
||||
overflow-y: auto;
|
||||
|
||||
}
|
||||
|
||||
.page-footer {
|
||||
@ -155,6 +156,10 @@
|
||||
ul.stepper:not(.horizontal) .step.active::before, ul.stepper:not(.horizontal) .step.done::before, ul.stepper.horizontal .step.active .step-title::before, ul.stepper.horizontal .step.done .step-title::before {
|
||||
background-color: #3f51b5 !important;
|
||||
}
|
||||
|
||||
.select-port-container {
|
||||
margin-top: 19px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
@ -171,7 +176,7 @@
|
||||
|
||||
<main>
|
||||
<div class="container">
|
||||
{% for file in files %}
|
||||
{% for file, full_path in zip(files, full_path_files) %}
|
||||
<div class="row">
|
||||
<div class="col s8 offset-s2 m10 offset-m1 l12">
|
||||
<div class="card horizontal">
|
||||
@ -180,10 +185,14 @@
|
||||
</div>
|
||||
<div class="card-stacked">
|
||||
<div class="card-content">
|
||||
<span class="card-title">{{ file }}</span>
|
||||
<span class="card-title">{{ escape(file) }}</span>
|
||||
<p>
|
||||
Full path: <code class="inlinecode">{{ escape(full_path) }}</code>
|
||||
</p>
|
||||
</div>
|
||||
<div class="card-action">
|
||||
<a href="#" class="action-upload" data-node="{{ file }}">Upload</a>
|
||||
<a href="#" class="action-compile" data-node="{{ file }}">Compile</a>
|
||||
<a href="#" class="action-show-logs" data-node="{{ file }}">Show Logs</a>
|
||||
</div>
|
||||
</div>
|
||||
@ -196,23 +205,14 @@
|
||||
<div id="modal-logs" class="modal modal-fixed-footer">
|
||||
<div class="modal-content">
|
||||
<h4>Show Logs</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">Close</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="modal-run" class="modal modal-fixed-footer">
|
||||
<div class="modal-content">
|
||||
<h4>Compile And Upload</h4>
|
||||
<div class="upload-port row">
|
||||
<div class="col s12">
|
||||
<h5>Found multiple serial ports, please choose one:</h5>
|
||||
</div>
|
||||
<div class="input-field col s8">
|
||||
<select></select>
|
||||
</div>
|
||||
<div class="col s4">
|
||||
<div class="col s4 select-port-container">
|
||||
<button class="btn waves-effect waves-light upload-port-submit" type="submit" name="action">Select
|
||||
<i class="material-icons right">send</i>
|
||||
</button>
|
||||
@ -223,6 +223,44 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<a class="modal-close waves-effect waves-green btn-flat">Close</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="modal-upload" class="modal modal-fixed-footer">
|
||||
<div class="modal-content">
|
||||
<h4>Compile And Upload</h4>
|
||||
<div class="upload-port row">
|
||||
<div class="col s12">
|
||||
<h5>Found multiple upload options, please choose one:</h5>
|
||||
</div>
|
||||
<div class="input-field col s8">
|
||||
<select></select>
|
||||
</div>
|
||||
<div class="col s4 select-port-container">
|
||||
<button class="btn waves-effect waves-light upload-port-submit" type="submit" name="action">Select
|
||||
<i class="material-icons right">send</i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<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</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="modal-compile" class="modal modal-fixed-footer">
|
||||
<div class="modal-content">
|
||||
<h4>Compile</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 disabled download-binary">Download Binary</a>
|
||||
<a class="modal-close waves-effect waves-green btn-flat">Stop</a>
|
||||
</div>
|
||||
</div>
|
||||
@ -259,7 +297,7 @@
|
||||
<p>
|
||||
First, I need to know what this node should be called. Choose this name wisely, changing this
|
||||
later makes Over-The-Air Update attempts difficult.
|
||||
It may only contain the characters <code class="inlinecode">a-z</code>, <code class="inlinecode">A-Z</code>,
|
||||
It may only contain the characters <code class="inlinecode">a-z</code>,
|
||||
<code class="inlinecode">0-9</code> and <code class="inlinecode">_</code>
|
||||
</p>
|
||||
<div class="input-field col s12">
|
||||
@ -268,7 +306,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="step-actions">
|
||||
<button class="waves-effect waves-dark btn indigo next-step" id="step-1-continue">CONTINUE</button>
|
||||
<button class="waves-effect waves-dark btn indigo next-step"">CONTINUE</button>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
@ -278,7 +316,8 @@
|
||||
<div class="row">
|
||||
<p>
|
||||
Great! Now I need to know what type of microcontroller you're using so that I can compile firmware for them.
|
||||
Please choose either ESP32 or ESP8266 (use ESP8266 for Sonoff devices).
|
||||
Please choose either ESP32 or ESP8266 (use ESP8266 for Sonoff devices). Note that the ESP32 is currently
|
||||
unsupported if HassIO is running on a Raspberry Pi.
|
||||
</p>
|
||||
<div class="input-field col s12">
|
||||
<select id="esp_type" name="platform" required>
|
||||
@ -347,8 +386,10 @@
|
||||
</p>
|
||||
<p>
|
||||
When you're done with that, please enter your MQTT broker here. For example
|
||||
<code class="inlinecode">hassio.local</code>. Please also specify the MQTT username and password
|
||||
you wish esphomelib to use (leave them empty if you're not using any authentication).
|
||||
<code class="inlinecode">192.168.1.100</code> (Note
|
||||
<code class="inlinecode">hassio.local</code> often doesn't work, please use a static IP).
|
||||
Please also specify the MQTT username and password you wish esphomelib to use
|
||||
(leave them empty if you're not using any authentication).
|
||||
</p>
|
||||
<div class="input-field col s12">
|
||||
<input id="mqtt_broker" class="validate" type="text" name="broker" required>
|
||||
@ -383,7 +424,8 @@
|
||||
<li>
|
||||
Flash the firmware. This can be done using the “UPLOAD” option in the dashboard. See
|
||||
<a href="https://esphomelib.com/esphomeyaml/index.html#using-with" target="_blank">this</a>
|
||||
for guides on how to flash different types of devices.
|
||||
for guides on how to flash different types of devices. Note that you need to restart this add-on
|
||||
for newly plugged in serial devices to be detected.
|
||||
</li>
|
||||
<li>
|
||||
See the <a href="https://esphomelib.com/esphomeyaml/index.html" target="_blank">esphomeyaml index</a>
|
||||
@ -468,68 +510,44 @@
|
||||
let configuration = "";
|
||||
const ws_url = 'ws://' + window.location.hostname + ':' + window.location.port;
|
||||
|
||||
document.querySelectorAll(".action-show-logs").forEach((showLogs) => {
|
||||
console.log(showLogs);
|
||||
showLogs.addEventListener('click', (e) => {
|
||||
configuration = e.target.getAttribute('data-node');
|
||||
const elem = document.getElementById("modal-logs");
|
||||
const instance = M.Modal.getInstance(elem);
|
||||
const log = elem.querySelector(".log");
|
||||
log.innerHTML = "";
|
||||
const logsModalElem = document.getElementById("modal-logs");
|
||||
const logsPortSelect = logsModalElem.querySelector('select');
|
||||
const logsPortDiv = logsModalElem.querySelector(".upload-port");
|
||||
const logsPortSubmit = logsModalElem.querySelector('.upload-port-submit');
|
||||
let logsStart = undefined;
|
||||
|
||||
instance.open();
|
||||
|
||||
const logSocket = new WebSocket(ws_url + "/logs");
|
||||
logSocket.addEventListener('message', (event) => {
|
||||
const data = JSON.parse(event.data);
|
||||
if (data.event === "line") {
|
||||
const msg = data.data;
|
||||
log.innerHTML += colorReplace(msg);
|
||||
}
|
||||
});
|
||||
logSocket.addEventListener('open', (event) => {
|
||||
logSocket.send(configuration);
|
||||
});
|
||||
logSocket.addEventListener('close', () => {
|
||||
M.toast({html: 'Terminated process.'});
|
||||
});
|
||||
|
||||
instance.options.onCloseStart = () => {
|
||||
logSocket.close();
|
||||
};
|
||||
});
|
||||
logsPortSubmit.addEventListener('click', () => {
|
||||
const inst = M.FormSelect.getInstance(logsPortSelect);
|
||||
logsStart(inst.getSelectedValues()[0]);
|
||||
inst.destroy();
|
||||
});
|
||||
|
||||
const modalRunElem = document.getElementById("modal-run");
|
||||
const submitButton = modalRunElem.querySelector('.upload-port-submit');
|
||||
let startRun = undefined;
|
||||
const select = modalRunElem.querySelector('select');
|
||||
const uploadPort = modalRunElem.querySelector(".upload-port");
|
||||
|
||||
document.querySelectorAll(".action-upload").forEach((actionUpload) => {
|
||||
actionUpload.addEventListener('click', (e) => {
|
||||
document.querySelectorAll(".action-show-logs").forEach((showLogs) => {
|
||||
showLogs.addEventListener('click', (e) => {
|
||||
configuration = e.target.getAttribute('data-node');
|
||||
|
||||
const modal_instance = M.Modal.getInstance(modalRunElem);
|
||||
if (M.FormSelect.getInstance(select) === undefined) {
|
||||
M.FormSelect.getInstance(select).destroy();
|
||||
}
|
||||
const log = modalRunElem.querySelector(".log");
|
||||
const modalInstance = M.Modal.getInstance(logsModalElem);
|
||||
const log = logsModalElem.querySelector(".log");
|
||||
log.innerHTML = "";
|
||||
|
||||
if (uploadPort.classList.contains('hide')) {
|
||||
uploadPort.classList.remove('hide');
|
||||
if (M.FormSelect.getInstance(logsPortSelect) !== undefined) {
|
||||
M.FormSelect.getInstance(logsPortSelect).destroy();
|
||||
}
|
||||
modalInstance.open();
|
||||
|
||||
if (logsPortDiv.classList.contains('hide')) {
|
||||
logsPortDiv.classList.remove('hide');
|
||||
}
|
||||
|
||||
modal_instance.open();
|
||||
|
||||
startRun = (port) => {
|
||||
const logSocket = new WebSocket(ws_url + "/run");
|
||||
logsStart = (port) => {
|
||||
logsPortDiv.classList.add('hide');
|
||||
const logSocket = new WebSocket(ws_url + "/logs");
|
||||
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") {
|
||||
M.toast({html: `Program exited with code ${data.code}`});
|
||||
}
|
||||
});
|
||||
logSocket.addEventListener('open', () => {
|
||||
@ -539,7 +557,7 @@
|
||||
logSocket.addEventListener('close', () => {
|
||||
M.toast({html: 'Terminated process.'});
|
||||
});
|
||||
modal_instance.options.onCloseStart = () => {
|
||||
modalInstance.options.onCloseStart = () => {
|
||||
logSocket.close();
|
||||
};
|
||||
};
|
||||
@ -547,26 +565,130 @@
|
||||
fetch('/serial-ports').then(res => res.json())
|
||||
.then(response => {
|
||||
if (response.length > 1) {
|
||||
select.innerHTML = "";
|
||||
logsPortSelect.innerHTML = "";
|
||||
for (let i = 0; i < response.length; i++) {
|
||||
const val = response[i];
|
||||
select.innerHTML += `<option value="${val.port}">${val.port} (${val.desc})</option>`;
|
||||
logsPortSelect.innerHTML += `<option value="${val.port}">${val.port} (${val.desc})</option>`;
|
||||
}
|
||||
M.FormSelect.init(select, {});
|
||||
M.FormSelect.init(logsPortSelect, {});
|
||||
} else {
|
||||
uploadPort.classList.add('hide');
|
||||
startRun("OTA");
|
||||
logsStart("OTA");
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
submitButton.addEventListener('click', () => {
|
||||
const inst = M.FormSelect.getInstance(select);
|
||||
console.log(inst.getSelectedValues());
|
||||
startRun(inst.getSelectedValues()[0]);
|
||||
const uploadModalElem = document.getElementById("modal-upload");
|
||||
const uploadPortSelect = uploadModalElem.querySelector('select');
|
||||
const uploadPortDiv = uploadModalElem.querySelector(".upload-port");
|
||||
const uploadPortSubmit = uploadModalElem.querySelector('.upload-port-submit');
|
||||
let uploadStart = undefined;
|
||||
|
||||
uploadPortSubmit.addEventListener('click', () => {
|
||||
const inst = M.FormSelect.getInstance(uploadPortSelect);
|
||||
uploadStart(inst.getSelectedValues()[0]);
|
||||
inst.destroy();
|
||||
uploadPort.classList.add('hide');
|
||||
});
|
||||
|
||||
document.querySelectorAll(".action-upload").forEach((showLogs) => {
|
||||
showLogs.addEventListener('click', (e) => {
|
||||
configuration = e.target.getAttribute('data-node');
|
||||
const modalInstance = M.Modal.getInstance(uploadModalElem);
|
||||
const log = uploadModalElem.querySelector(".log");
|
||||
log.innerHTML = "";
|
||||
|
||||
if (M.FormSelect.getInstance(uploadPortSelect) !== undefined) {
|
||||
M.FormSelect.getInstance(uploadPortSelect).destroy();
|
||||
}
|
||||
modalInstance.open();
|
||||
|
||||
if (uploadPortDiv.classList.contains('hide')) {
|
||||
uploadPortDiv.classList.remove('hide');
|
||||
}
|
||||
|
||||
uploadStart = (port) => {
|
||||
uploadPortDiv.classList.add('hide');
|
||||
const logSocket = new WebSocket(ws_url + "/run");
|
||||
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") {
|
||||
M.toast({html: `Program exited with code ${data.code}`});
|
||||
}
|
||||
});
|
||||
logSocket.addEventListener('open', () => {
|
||||
const msg = JSON.stringify({configuration: configuration, port: port});
|
||||
logSocket.send(msg);
|
||||
});
|
||||
logSocket.addEventListener('close', () => {
|
||||
M.toast({html: 'Terminated process.'});
|
||||
});
|
||||
modalInstance.options.onCloseStart = () => {
|
||||
logSocket.close();
|
||||
};
|
||||
};
|
||||
|
||||
fetch('/serial-ports').then(res => res.json())
|
||||
.then(response => {
|
||||
if (response.length > 1) {
|
||||
uploadPortSelect.innerHTML = "";
|
||||
for (let i = 0; i < response.length; i++) {
|
||||
const val = response[i];
|
||||
uploadPortSelect.innerHTML += `<option value="${val.port}">${val.port} (${val.desc})</option>`;
|
||||
}
|
||||
M.FormSelect.init(uploadPortSelect, {});
|
||||
} else {
|
||||
uploadStart("OTA");
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
const compileModalElem = document.getElementById("modal-compile");
|
||||
const downloadButton = compileModalElem.querySelector('.download-binary');
|
||||
|
||||
document.querySelectorAll(".action-compile").forEach((showLogs) => {
|
||||
showLogs.addEventListener('click', (e) => {
|
||||
configuration = e.target.getAttribute('data-node');
|
||||
const modalInstance = M.Modal.getInstance(compileModalElem);
|
||||
const log = compileModalElem.querySelector(".log");
|
||||
log.innerHTML = "";
|
||||
downloadButton.classList.add('disabled');
|
||||
modalInstance.open();
|
||||
|
||||
const logSocket = new WebSocket(ws_url + "/compile");
|
||||
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") {
|
||||
M.toast({html: `Program exited with code ${data.code}`});
|
||||
if (data.code === 0) {
|
||||
downloadButton.classList.remove('disabled');
|
||||
}
|
||||
}
|
||||
});
|
||||
logSocket.addEventListener('open', () => {
|
||||
const msg = JSON.stringify({configuration: configuration});
|
||||
logSocket.send(msg);
|
||||
});
|
||||
logSocket.addEventListener('close', () => {
|
||||
M.toast({html: 'Terminated process.'});
|
||||
});
|
||||
modalInstance.options.onCloseStart = () => {
|
||||
logSocket.close();
|
||||
};
|
||||
});
|
||||
});
|
||||
|
||||
downloadButton.addEventListener('click', () => {
|
||||
const link = document.createElement("a");
|
||||
link.download = name;
|
||||
link.href = '/download.bin?configuration=' + encodeURIComponent(configuration);
|
||||
link.click();
|
||||
});
|
||||
|
||||
const modalSetupElem = document.getElementById("modal-wizard");
|
||||
@ -586,14 +708,6 @@
|
||||
showFeedbackLoader: true,
|
||||
parallel: false
|
||||
});
|
||||
|
||||
document.getElementById('#step-1-continue').addEventListener('click', () => {
|
||||
console.log("NEXT STEP");
|
||||
$('.stepper').nextStep();
|
||||
});
|
||||
$('#step-1-continue').on('click', () => {
|
||||
|
||||
});
|
||||
};
|
||||
setupWizardStart.addEventListener('click', startWizard);
|
||||
</script>
|
||||
|
Loading…
x
Reference in New Issue
Block a user