Skip to content

Instantly share code, notes, and snippets.

@arthurwolf
Last active September 2, 2018 22:20
Show Gist options
  • Save arthurwolf/26ae33998b4efbb4e566be143f968a4e to your computer and use it in GitHub Desktop.
Save arthurwolf/26ae33998b4efbb4e566be143f968a4e to your computer and use it in GitHub Desktop.
✘ arthur@aquarelle ~/dev/js/Smoothie > ack connection_log
src/connect/views/Connect.vue
17: <LogList title="Connection log" v-bind:items="communication.connection_log"></LogList>
src/index/views/Home.vue
17: <LogList title="Connection log" v-bind:items="communication.connection_log"></LogList>
dist/javascript/machine.js
137: machine.communication.connection_log.push(reason, {icon: 'times', color: 'danger'});
dist/javascript/communication.js
3: this.connection_log = new Log();
17: that.connection_log.push(`Attempting connection to ${what_to} <kbd>${address}</kbd>`, {icon: 'stethoscope', color: 'default'});
22: that.connection_log.push(`Succesful connection to <kbd>${address}</kbd>`, {icon: 'thumbs-up', color: 'success'});
26: that.connection_log.push(`No answer from <kbd>${address}</kbd>`, {icon: 'phone-slash', color: 'warning'});
75: this.connection_log.empty();
94: this.connection_log.push(`<div class="card"><div class="card-header">Responsive board discovered at address <kbd>${address}</kbd> answered : </div><div class="card-body"><pre>${data}</pre></div></div>`, {icon: 'code-branch', color: 'default'});
125: this.connection_log.push(`Going to the interface now`, {icon: 'truck-moving', color: 'default'});
public/javascript/machine.js
7: console.log(this.communication.connection_log);
8: console.log(this.communication.connection_log.add);
100: console.log(machine.communication.connection_log);
101: console.log(machine.communication.connection_log.add);
147: console.log(machine.communication.connection_log);
148: console.log(machine.communication.connection_log.add);
150: machine.communication.connection_log.add(reason, {icon: 'times', color: 'danger'});
163:console.log(machine.communication.connection_log); // Array [ ]
164:console.log(machine.communication.connection_log.add); // function add()
172: console.log(machine.communication.connection_log); // Array [ ]
173: console.log(machine.communication.connection_log.add); // undefined
public/javascript/communication.js
3: this.connection_log = new Log();
5: console.log(this.connection_log);
6: console.log(this.connection_log.add);
21: console.log(that.connection_log);
22: console.log(that.connection_log.add);
26: that.connection_log.add(`Attempting connection to ${what_to} <kbd>${address}</kbd>`, {icon: 'stethoscope', color: 'default'});
31: that.connection_log.add(`Succesful connection to <kbd>${address}</kbd>`, {icon: 'thumbs-up', color: 'success'});
35: that.connection_log.add(`No answer from <kbd>${address}</kbd>`, {icon: 'phone-slash', color: 'warning'});
84: //TODO: EMPTY THE LOG this.connection_log = new Log();
103: this.connection_log.add(`<div class="card"><div class="card-header">Responsive board discovered at address <kbd>${address}</kbd> answered : </div><div class="card-body"><pre>${data}</pre></div></div>`, {icon: 'code-branch', color: 'default'});
134: this.connection_log.add(`Going to the interface now`, {icon: 'truck-moving', color: 'default'});
class Machine {
// Create a new Machine object representing a Smoothieboard and machine
constructor(){
this.communication = new Communication(this);
console.log("In machine constructor");
console.log(this.communication.connection_log);
console.log(this.communication.connection_log.add);
console.log(Log);
this.log = new Log();
this.config = new Config();
this.version_data = {};
this.version_answer = '';
this.config_file_name = '';
}
// Obtain configuration from memory or from the SD card, and process it
configure(address, data){
// Remember the address
this.communication.url = address;
// Parse the data
this.parse_version(data);
// Get configuration from the SD card
var that = this;
return new Promise(function(resolve, reject){
// First obtain configuration file
that.log.add("Obtaining configuration", {icon: 'sliders-h'});
// What to do if an actual configuration file is found
var config_found = (file_name, config_file_content) => {
that.log.add(`Success obtaining configuration file named <kbd>${file_name}</kbd>`, {icon: 'thumbs-up', color: 'success'})
// Save the content to cache so we don't need to grab it each page load
storage.write("config_file_cache_age", Date.now());
storage.write("config_file_cache_filename", file_name);
storage.write("config_file_cache", config_file_content);
// Parse the configuration
that.log.add("Parsing new configuration", {icon: "cogs", color: 'primary'});
that.config.parse(file_name, config_file_content).then((reaction) => {
// Configuration parsing went well
that.log.add(`Success parsing configuration file`, {icon: 'thumbs-up', color: 'success'})
}).catch((reason) => {
console.log("failed parsing config " + reason);
});
};
// Attempt to find a previous retreival of the configuration file in local storage
var config_file_cache_age = storage.read("config_file_cache_age") || 0;
var age = Math.round((Date.now() - config_file_cache_age)/1000);
if( age < 5 * 60 ){ // If configuration was last grabbed less than 5 minutes ago // TODO: Make configurable
that.log.add(`Using configuration file saved in cache, ${age} seconds old`, {icon: "memory", color: 'default'});
var config_file_cache = storage.read("config_file_cache");
var config_file_cache_filename = storage.read("config_file_cache_filename");
config_found(config_file_cache_filename, config_file_cache);
resolve("Config found");
return;
}
// Attempt for file named "config.txt"
machine.communication.get_file('/sd/config.txt').then((response) => {
config_found("config.txt", response);
resolve("Config found");
}).catch((response) => {
// File named "config.txt" was not found, try just "config" instead
machine.communication.get_file('/sd/config').then((response) => {
config_found("config", response);
resolve("Config found");
}).catch((response) => {
that.log.add("No configuration file was found, something is very wrong, check your SD card " + response, {icon: 'times', color: 'danger'});
reject("Neither config file names were found " + response);
});
});
});
}
// Parse the answer to the version and M115 commands
parse_version(answer){
// Save the version string in case we want to skip asking the board for it next time
storage.write("last_version_answer", answer);
// Save reply
this.version_answer = answer;
var lines = answer.split('\n');
var that = this;
lines[2].split(/\,\s*/).forEach(function(element){
var cut = element.split(':');
var key = cut[0];
var value = cut.slice(1).join(':');
that.version_data[key] = value;
});
};
// Attempt connection to possible targets, when page is loaded
try_to_find_machine(){
console.log("Try to find machine");
console.log(machine.communication.connection_log);
console.log(machine.communication.connection_log.add);
console.log(Log);
// Before we start trying to connect to addresses with actual calls, lets see if possibly we already have a recent connection
// First let's figure out how recently a good call was made to a machine
var last_machine_call_age = storage.read("last_machine_call_age") || 0;
var age = Math.round((Date.now() - last_machine_call_age)/1000);
// If a machine answered more recently than 60 seconds
if( age < 60 ){
// Since we won't be asking the board for it's version strings/commands,
// get the version answer from local storage instead
var version_answer = storage.read("last_version_answer");
// Same thing for the address, the one saved is the latest that worked
var address = storage.read('current_machine_address');
// "Simulate" having found a board using data from memory
this.communication.found_board(address, version_answer);
}else{
// Notice ( event ) we are going to try to connect, for example to display log modals and such
this.communication.on_connecting.call();
// We couldn't remember a connection to avoid a call, lets's start making actual calls now
// A list of addresses to try
var addresses_to_try = [];
// Get the "current" machine address, which should be the address that worked last time
var current_machine_address = storage.read('current_machine_address');
if( current_machine_address != null ){ addresses_to_try.push({address: current_machine_address, to_what: "last working address"}); }
// Add the root address, we need to try it no matter what if the current machine address didn't work
addresses_to_try.push({address: '/', to_what: "default path"});
// Finally add all the addresses in that ever worked
storage.read('previous_addresses').forEach((address) => {
// But make sure we don't try the current address twice if it's in the "historical" list too
if( current_machine_address != address ){ addresses_to_try.push({address: address, to_what: "historically working address"}); }
});
// Try all of these addresses
machine.communication.try_address_list(addresses_to_try).then((result) => {
console.log("One address answered in the list : " + result);
}).catch((reason) => {
console.log("In final call");
console.log(machine.communication.connection_log);
console.log(machine.communication.connection_log.add);
console.log(Log);
machine.communication.connection_log.add(reason, {icon: 'times', color: 'danger'});
console.log("Failed try address list, reason: " + reason);
});
}
}
}
var machine = new Machine();
console.log("After instantiation");
console.log(machine.communication.connection_log); // Array [ ]
console.log(machine.communication.connection_log.add); // function add()
console.log(Log); // function Log()
// This gets executed once the page is loaded, this is where it all begins
// When the page is loaded, we try connecting to an active board
$(function() {
console.log("In on_load");
console.log(machine.communication.connection_log); // Array [ ]
console.log(machine.communication.connection_log.add); // undefined
console.log(Log); // function Log()
// Try to connect to possible targets
machine.try_to_find_machine();
});
class Communication{
constructor(parent){
this.connection_log = new Log();
console.log("In constructor");
console.log(this.connection_log);
console.log(this.connection_log.add);
console.log(Log);
this.url = '/';
this.try_address_list_failed = false;
this.machine = parent;
this.connected = false;
this.on_connected = () => {};
this.on_connecting = () => {};
}
// Attempt connection to a given IP address
attempt_connection(what_to = '', address){
var that = this;
return new Promise(function(resolve,reject){
console.log("In attempt connection");
console.log(that.connection_log);
console.log(that.connection_log.add);
console.log(Log);
// Log
that.connection_log.add(`Attempting connection to ${what_to} <kbd>${address}</kbd>`, {icon: 'stethoscope', color: 'default'});
// Attempt connection to this given address
that.command(['version', 'M115'], false, false, address).then((result) => {
// We reached a board that answered
that.connection_log.add(`Succesful connection to <kbd>${address}</kbd>`, {icon: 'thumbs-up', color: 'success'});
resolve(result);
}).catch((data) => {
// We got no answer
that.connection_log.add(`No answer from <kbd>${address}</kbd>`, {icon: 'phone-slash', color: 'warning'});
reject();
});
});
}
// Attempt connection to a list of IP addresses
try_address_list( address_list = [] ){
// Attempt connection to first address
var that = this;
return new Promise(function(resolve,reject){
// If there are no more addresses to try
if( address_list.length === 0 ){
that.try_address_list_failed = true;
reject("No more addresses to try");
// If we are not on the "connect" page, we need to go there now
if( !window.location.pathname.match(/^\/connect\.html/) ){
window.location.replace("/connect.html");
}
}else{
// Note that we have not failed yet
that.try_address_list_failed = false;
// Get first address to try
var target = address_list.shift();
// Attempt connection to it
that.attempt_connection(target.to_what, target.address).catch(function(){
// If connection failed, try the next one
that.try_address_list( address_list ).catch((reason) => {reject(reason)});
}).then(function(result){
if( result == undefined ){ return; }
// We found a board to talk to !
that.found_board(target.address, result);
// Resolve the promise positively
resolve(result);
});
}
});
}
// Attempt connection to a single address
try_single_address( address = '' ){
// Empty the log
//TODO: EMPTY THE LOG this.connection_log = new Log();
// We don't know if we failed yet
this.try_address_list_failed = false;
var that = this;
return new Promise(function(resolve, reject){
// Actually try
that.try_address_list([{
address: address,
to_what: 'user-provided address'
}]).then((result) => { resolve(result); }).catch((reason) => { reject(reason); });
});
}
// Found a board that answered the "version" command, "data" is the answer
found_board(address, data){
// Log the discovery
this.connection_log.add(`<div class="card"><div class="card-header">Responsive board discovered at address <kbd>${address}</kbd> answered : </div><div class="card-body"><pre>${data}</pre></div></div>`, {icon: 'code-branch', color: 'default'});
// Save this new discovery by saving the previous current address to the history of addresses, then replacing it with this new address
// First backup the current address so we can overwrite it
var current_machine_address = storage.read('current_machine_address');
// Get the log of previous_addresses
var previous_addresses = new Set(storage.read('previous_addresses'));
// Add the previous current address
if( !previous_addresses.has(current_machine_address) ){ previous_addresses.add(current_machine_address); }
// Save the list
storage.write('previous_addresses', Array.from(previous_addresses));
// Overwrite the current machine address
storage.write('current_machine_address', address);
// Notice we are now connected
setTimeout(() => {
this.connected = true;
this.on_connected.call();
}, 1000);
// If this is the "connect" page, move along to another page
if( window.location.pathname.match(/^\/connect\.html/) ){
// Configure the machine
this.machine.configure(address, data).then(() => {
// Machine was configured correctly
// Log
this.connection_log.add(`Going to the interface now`, {icon: 'truck-moving', color: 'default'});
// Go to the index page
window.location.replace("/index.html");
}).catch((reason) => {
console.log(`ERROR in machine configure, WTH : ${reason}`);
});
}else{
// We are in a page and actually need to do something
// Configure the machine
this.machine.configure(address, data).then(() => {
// Machine was configured correctly
//console.log("Machine configured");
}).catch((reason) => {
// Something went wrong with the configuration phase
console.log(`ERROR in machine configure, WTH : ${reason}`);
});
}
}
// Get a file
get_file( file_name = '', base_address = this.url ){
return new Promise(function(resolve,reject){
// Format address
var address = base_address;
if( base_address != '/' ){ address = `http://${base_address}`; }else{ base_address = ''; }
// Get the file
//$.get(address + file_name).done((data) => { resolve(data); }).fail((problem) => { reject(problem); });
$.get(address + file_name).done(resolve).fail(reject);
});
}
// Run a command
command(commands = [], silent = false, to_log = true, base_address = this.url) {
// Get the actual command string to send
var cmd = commands.join("\n") + "\n";
// Check if this is a play command
var playing = cmd.match(/^play (.*)/);
// Format address
var address = base_address;
if( base_address != '/' ){ address = `http://${base_address}/`;}
// Actually call the command
return new Promise(function(resolve,reject){
// JQuery POST call
$.post( address + (silent ? "command_silent" : "command") , cmd + "\n" ).done(( data ) => {
// Note when we got a good call, so we can remember how long it's been since the last one
storage.write("last_machine_call_age", Date.now());
// Preserve the data
var original_data = data;
// If this started a play sequence
if( playing ){ machine.playing = true; }
// Resolve as successfull
resolve(original_data);
}).fail((data) => {
reject(data);
});
});
/*
//if( playing ){$("#playing_modal").modal({backdrop: 'static', keyboard: false});}
// Send the data using post
$.post( machine.url + (silent ? "command_silent" : "command") , cmd + "\n" ).done(function( data ) {
var original_data = data;
if( to_log ){
var state = getCommandState(cmd, data);
var rnd = Math.floor((Math.random() * 1000000) + 1).toString();
var lines = data.split("\n");
if( lines.length >= 4 ){
data = "<pre>" + lines.slice(0,4).join("\n") + "</pre>";
data += "<button type='button' class='btn btn-dark btn-sm' data-toggle='collapse' data-target='#" + rnd + "' aria-expanded='false' aria-controls='" + rnd + "'>Show " + Number(lines.length-5) + " lines more</button>";
data += "<pre class='collapse' id='" + rnd + "'>" + lines.slice(4 ).join("\n") + "</pre>";
}else{
data = "<pre>" + data + "</pre>";
}
var result = "<li> <i class='milestone-default fas fa-arrow-right'></i> <kbd>" + cmd + "</kbd></li><li><i class='milestone-" + state.answer + " fas fa-" + state.icon + "'></i>" + data + "</li>";
// Display command result
$( "#command_result" ).empty().append( result.replace(new RegExp(rnd,"g"),rnd+'a') );
$('#command_result').fadeIn(100).fadeOut(100).fadeIn(100).fadeOut(100).fadeIn(100);
// Add to command log
$("#command_log").append(result.replace(new RegExp(rnd,"g"),rnd+'b'));
// Handle starting playing a file
if( playing ){
machine.playing = true;
//status_loop();
}
// Handle abort Commands
if( cmd.match(/^abort/) ){ machine.playing = false; }
// Call callbacks
deferred.resolve(original_data);
}).fail(function(data){
deferred.reject(original_data);
});
return deferred;
}
*/
}
}
var machine = new Machine();
console.log("After instantiation");
console.log(machine.communication.connection_log); // Array [ ]
console.log(machine.communication.connection_log.add); // function add()
console.log(Log); // function Log()
// This gets executed once the page is loaded, this is where it all begins
// When the page is loaded, we try connecting to an active board
$(function() {
console.log("In on_load");
console.log(machine.communication.connection_log); // Array [ ]
console.log(machine.communication.connection_log.add); // undefined
console.log(Log); // function Log()
// Try to connect to possible targets
machine.try_to_find_machine();
});
class LogItem{
constructor(text, icon, color = 'default'){
this.text = text;
this.icon = icon;
this.color = color;
}
}
class Log extends Array{
constructor() {
console.log("Creating Log");
super();
}
static get [Symbol.species]() { return Log; };
add(text = '', properties = {}){
console.log(text);
this.push(new LogItem(text, properties.icon, properties.color));
}
}
var test = new Log();
console.log("In global scope");
console.log(test);
console.log(test.add);
console.log(Log);
In global scope log.js:20:1
Array [ ] log.js:21:1
function add() log.js:22:1
function Log() log.js:23:1
In constructor communication.js:4:7
Array [ ] communication.js:5:7
function add() communication.js:6:7
function Log() communication.js:7:7
In machine constructor machine.js:6:7
Array [ ] machine.js:7:7
function add() machine.js:8:7
function Log() machine.js:9:7
After instantiation machine.js:162:1
Array [ ] machine.js:163:1
function add() machine.js:164:1
function Log() machine.js:165:1
[HMR] Waiting for update signal from WDS... log.js:24:4
In on_load machine.js:171:3
Array [ ] machine.js:172:3
undefined machine.js:173:3
function Log() machine.js:174:3
Try to find machine machine.js:99:5
Array [ ] machine.js:100:5
undefined machine.js:101:5
function Log() machine.js:102:5
In attempt connection communication.js:20:9
Array [ ] communication.js:21:9
undefined communication.js:22:9
function Log() communication.js:23:9
In attempt connection communication.js:20:9
Array [ ] communication.js:21:9
undefined communication.js:22:9
function Log() communication.js:23:9
In attempt connection communication.js:20:9
Array [ ] communication.js:21:9
undefined communication.js:22:9
function Log() communication.js:23:9
In final call machine.js:146:9
Array [ ] machine.js:147:9
undefined machine.js:148:9
function Log() machine.js:149:9
Use of getPreventDefault() is deprecated. Use defaultPrevented instead. jquery-1.9.1.js:3346:28
Unhandled promise rejection TypeError: machine.communication.connection_log.add is not a function
Stack trace:
try_to_find_machine/<@http://localhost:8080/javascript/machine.js:150:9
notify/</run@webpack-internal:///./node_modules/core-js/modules/es6.promise.js:75:22
notify/<@webpack-internal:///./node_modules/core-js/modules/es6.promise.js:92:30
module.exports/flush@webpack-internal:///./node_modules/core-js/modules/_microtask.js:18:9
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment