Skip to content

Commit

Permalink
Merge pull request #64 from PropGit/master
Browse files Browse the repository at this point in the history
Fixed CrOS v74+ port issues in Windows
  • Loading branch information
PropGit authored May 29, 2019
2 parents 3106e5e + 9f7180f commit 9af05b4
Show file tree
Hide file tree
Showing 6 changed files with 76 additions and 49 deletions.
28 changes: 18 additions & 10 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,14 @@ const pfMac = 3;
const pfWin = 4;
var platform = pfUnk;

// Windows default port origin
const winPortOrigin = '\\\\.\\';
const winPortOriginLen = 4;

/* Serial port ID pattern (index into with platform value)
Unknown ChromeOS Linux macOS Windows */
portPattern = ["", "/dev/ttyUSB", "dev/tty", "/dev/cu.usbserial", "COM"];
portDelim = ["", "/", "/", "/", "\\"];

// Http and ws servers
var server = new http.Server();
Expand Down Expand Up @@ -280,7 +285,7 @@ function connect_ws(ws_port, url_path) {
socket.addEventListener('message', function(e) {
if (isJson(e.data)) {
var ws_msg = JSON.parse(e.data);

//Note: ws.msg.portPath is now really a "pathless" portName but kept named as-is for legacy support
// load the propeller
if (ws_msg.type === "load-prop") {
log('Received Propeller Application for ' + ws_msg.action);
Expand Down Expand Up @@ -393,7 +398,10 @@ function scanWPorts() {
let wln = [];
// update wired ports
portlist.forEach(function(port) {
if ((port.path.indexOf(portPattern[platform]) === 0) && (port.displayName.indexOf(' bt ') === -1 && port.displayName.indexOf('bluetooth') === -1)) {
// Get consistently formatted port path; If Windows, strip off possible leading port origin path for ease in comparison
var portPath = ((platform === pfWin) && (port.path.indexOf(winPortOrigin) === 0)) ? port.path.slice(winPortOriginLen) : port.path;
// Add only proper port types (platform specific and excluding bluetooth ports)
if ((portPath.indexOf(portPattern[platform]) === 0) && (port.displayName.indexOf(' bt ') === -1 && port.displayName.indexOf('bluetooth') === -1)) {
addPort({path: port.path});
}
});
Expand All @@ -415,7 +423,7 @@ function sendPortList(socket) {
let wln = [];
// log("sendPortList() for socket " + socket.pSocket_.socketId, mDbug);
// gather separated and sorted port lists (wired names and wireless names)
ports.forEach(function(p) {if (p.isWired) {wn.push(p.path)} else {wln.push(p.path)}});
ports.forEach(function(p) {if (p.isWired) {wn.push(p.name)} else {wln.push(p.name)}});
wn.sort();
wln.sort();

Expand All @@ -435,9 +443,9 @@ function helloClient(sock, baudrate) {

//TODO Check send results and act accordingly?
//TODO refactor to combine usb and wx-based port code efficiently
function serialTerminal(sock, action, portPath, baudrate, msg) {
// Find port from portPath
let port = findPort(byPath, portPath);
function serialTerminal(sock, action, portName, baudrate, msg) {
// Find port from portName
let port = findPort(byName, portName);
if (port) {
// Convert msg from string or buffer to an ArrayBuffer
if (typeof msg === 'string') {
Expand All @@ -447,10 +455,10 @@ function serialTerminal(sock, action, portPath, baudrate, msg) {
}
if (action === "open") {
// Open port for terminal use
openPort(sock, portPath, baudrate, 'debug')
.then(function() {log('Connected terminal to ' + portPath + ' at ' + baudrate + ' baud.');})
openPort(sock, port.name, baudrate, 'debug')
.then(function() {log('Connected terminal to ' + portName + ' at ' + baudrate + ' baud.');})
.catch(function() {
log('Unable to connect terminal to ' + portPath);
log('Unable to connect terminal to ' + portName);
var msg_to_send = {type:'serial-terminal', msg:'Failed to connect.\rPlease close this terminal and select a connected port.'};
sock.send(JSON.stringify(msg_to_send));
});
Expand All @@ -466,7 +474,7 @@ function serialTerminal(sock, action, portPath, baudrate, msg) {
}
}
} else {
var msg_to_send = {type:'serial-terminal', msg:'Port ' + portPath + ' not found.\rPlease close this terminal and select an existing port.'};
var msg_to_send = {type:'serial-terminal', msg:'Port ' + portName + ' not found.\rPlease close this terminal and select an existing port.'};
sock.send(JSON.stringify(msg_to_send));
}
}
Expand Down
14 changes: 7 additions & 7 deletions loader.js
Original file line number Diff line number Diff line change
Expand Up @@ -95,10 +95,10 @@ function deferredPromise() {
//TODO Determine why port not found error message is not getting back to the UI
//TODO Determine how to gracefully handle the need to reset baudrate if error occurs but port is valid (as opposed to error caused by invalid port
//TODO Remove hard-coded example applications
function loadPropeller(sock, portPath, action, payload, debug) {
/* Download payload to Propeller with action on portPath. If debug, keep port open for communication with sock.
function loadPropeller(sock, portName, action, payload, debug) {
/* Download payload to Propeller with action on portName. If debug, keep port open for communication with sock.
sock may be null (if for development purposes)
portPath is wired or wireless port's pathname
portName is wired or wireless port's name
action is 'RAM' or 'EEPROM'
payload is base-64 encoded .elf, .binary, or .eeprom data containing the Propeller Application image
debug is true if a terminal is intended to connect to the Propeller after download; false otherwise*/
Expand All @@ -114,7 +114,7 @@ function loadPropeller(sock, portPath, action, payload, debug) {
}

// Look for an existing port
let port = findPort(byPath, portPath);
let port = findPort(byName, portName);
if (port) {
// Port found
let connect;
Expand All @@ -129,7 +129,7 @@ function loadPropeller(sock, portPath, action, payload, debug) {
} else {
// No connection yet, prep to create one
originalBaudrate = initialBaudrate;
connect = function() {return openPort(sock, portPath, initialBaudrate, "programming")}
connect = function() {return openPort(sock, portName, initialBaudrate, "programming")}
}
} else {
//TODO Retrieve actual current baudrate
Expand All @@ -140,7 +140,7 @@ function loadPropeller(sock, portPath, action, payload, debug) {
// Use connection to download application to the Propeller
connect()
.then(function() {listen(port, true)}) //Enable listener
.then(function() {log(notice(000, ["Scanning port " + portPath]), mUser, sock)}) //Notify what port we're using
.then(function() {log(notice(000, ["Scanning port " + portName]), mUser, sock)}) //Notify what port we're using
.then(function() {return talkToProp(sock, port, binImage, action === 'EEPROM')}) //Download user application to RAM or EEPROM
.then(function() {return changeBaudrate(port, originalBaudrate)}) //Restore original baudrate
.then(function() { //Success! Open terminal or graph if necessary
Expand All @@ -167,7 +167,7 @@ function loadPropeller(sock, portPath, action, payload, debug) {
.catch(function(e) {log(e.message, mAll, sock);});
} else {
// Port not found
log(notice(neCanNotFindPort, [portPath]), mAll, sock);
log(notice(neCanNotFindPort, [portName]), mAll, sock);
}
}

Expand Down
2 changes: 1 addition & 1 deletion manifest.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "BlocklyProp Launcher",
"description": "A Chrome application that connects your Propeller-Powered Hardware to the BlocklyProp website.",
"version": "0.9.7",
"version": "0.9.8",
"manifest_version": 2,
"minimum_chrome_version": "45",

Expand Down
41 changes: 30 additions & 11 deletions port.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ const byPHID = "phSocket"; //Represents numeric Propeller HTTP Socket ID
const byPTID = "ptSocket"; //Represents numeric Propeller Telnet Socket ID type
const byMAC = "mac"; //Represents alphanumeric MAC address type
const byPath = "path"; //Represents alphanumeric path (wired/wireless port identifier) type
const byName = "name"; //Represents alphanumeric name (wired/wireless port identifier) type

// Port's max lifetime
const wLife = 2;
Expand All @@ -25,7 +26,12 @@ const serPacket = {
timer : null,
};

function makePortName(mac) {
function makePortName(name) {
/* Return friendly port name, excluding leading path.*/
return name.slice(name.lastIndexOf(portDelim[platform])+1);
}

function makeWLPortName(mac) {
/* Return wireless fabricated name in the form 'wx-#######' using last 6 digits of it's MAC address.*/
return 'wx-' + mac.substr(9,16).replace(/\:/g,'');
}
Expand All @@ -45,19 +51,20 @@ function addPort(alist) {

if (!exists("path", alist)) {return}
if (!alist.path) {
//Empty port path? If wireless port details provided, craft path from mac, else abort (return)
if (get("ip", alist, "") && get("mac", alist, "")) {alist.path = makePortName(alist.mac)} else {return}
//Empty port path? If wireless port details provided, craft port name from mac, else abort (return)
if (get("ip", alist, "") && get("mac", alist, "")) {alist.path = makeWLPortName(alist.mac)} else {return}
}
// Look for existing port (mac used for wireless ports since path may have changed since last discovery)
// Look for existing port (mac used for wireless ports since path/name may have changed since last discovery)
let port = (get("mac", alist, "")) ? findPort(byMAC, alist.mac) : findPort(byPath, alist.path);
if (port) {
// Exists already? Update it's (portPath or iP)
// Exists already? Update it's (portPath/Name or iP)
updatePort(port, alist);
} else {
// else, add it as a new port record (all fields included; many with default values to be updated later)
log("Adding port: " + alist.path, mDbug);
ports.push({
path : alist.path, /*[<>""] Wired port path, or wireless port's custom name, or fabricated name; never empty*/
name : makePortName(alist.path), /*[<>""] Friendly port name; never empty, does not include path*/
path : alist.path, /*[<>""] Wired port path+name, or wireless port's custom name, or fabricated name; never empty*/
connId : get("connId", alist, null), /*[null+] Holds wired serial port's connection id (if open), null (if closed)*/
mac : get("mac", alist, ""), /*[""+] Holds wireless port's MAC address*/
ip : get("ip", alist, ""), /*[""+] Wireless port's IP address; */
Expand All @@ -81,6 +88,7 @@ function updatePort(port, alist) {
/* Update port attributes if necessary. Automatically handles special case of baudrate changes.
port: [required] port object to update
alist: [required] one or more attributes of port to update. Unchanging attributes can be omitted. Possible attributes are:
name: the friendly name of the port (not including path). Can be empty ("") and a name will be created from path
path: the string path to the wired serial port, or custom name of wireless port. Can be empty ("") and a wireless name will be fabricated from the MAC address
connId: unique identifier for the wired serial port connection id
ip: the wireless port's IP address
Expand All @@ -96,12 +104,20 @@ function updatePort(port, alist) {
if (exists(attr, alist)) {port[attr] = alist[attr]}
}

if (exists("path", alist) && !alist.path) {
// Empty port path? If wireless port, craft path from mac, else abort (reject)
if (port.isWireless && port.mac) {alist.path = makePortName(port.mac)} else {reject(Error("path required!")); return}
if (exists("path", alist)) {
if (!alist.path) {
// Empty port path? If wireless port, craft path from mac, else abort (reject)
if (port.isWireless && port.mac) {alist.path = makeWLPortName(port.mac)} else {reject(Error("path required!")); return}
}
if (exists("name", alist) && !alist.name) {
// Empty port name? Create it.
alist.name = makePortName(alist.path);
}
}

// log("Updating port '" + port.path + "' with " + alist, mDbug);
// Apply updates (if necessary) as well as special handling
set("name");
set("path");
set("connId");
set("ip");
Expand Down Expand Up @@ -131,6 +147,7 @@ function findPortIdx(type, clue) {
byPTID / numeric Propeller Telnet Socket ID
byMAC / alphanumeric MAC address
byPath / alphanumeric path (wired/wireless port identifier)
byName / alphanumeric name (wired/wireless port identifier)
Returns -1 if not found*/
return ports.findIndex(function(p) {return p[type] === clue});
}
Expand All @@ -143,14 +160,15 @@ function findPort(type, clue) {
byPTID / numeric Propeller Telnet Socket ID
byMAC / alphanumeric MAC address
byPath / alphanumeric path (wired/wireless port identifier)
byName / alphanumeric name (wired/wireless port identifier)
Returns null if not found*/
let cn = 0;
// Find port record based on scan function
function findConn(scan) {
while (cn < ports.length && !scan()) {cn++}
return cn < ports.length ? ports[cn] : null;
}
// Scan for ID, MAC, or path
// Scan for ID, MAC, path, or name
return findConn(function() {return ports[cn][type] === clue})
}

Expand All @@ -161,7 +179,8 @@ function deletePort(type, clue) {
byPHID / numeric Propeller HTTP Socket ID
byPTID / numeric Propeller Telnet Socket ID
byMAC / alphanumeric MAC address
byPath / alphanumeric path (wired/wireless port identifier)*/
byPath / alphanumeric path (wired/wireless port identifier)
byName / alphanumeric name (wired/wireless port identifier)*/
let idx = findPortIdx(type, clue);
if (idx > -1) {
log("Deleting port: " + ports[idx].path, mDbug);
Expand Down
Loading

0 comments on commit 9af05b4

Please sign in to comment.