Skip to content

Commit

Permalink
fix Windows issue by not reconnecting when a saved file gets opened.
Browse files Browse the repository at this point in the history
  • Loading branch information
kaspesla committed Nov 6, 2015
1 parent 0ca6401 commit bb30295
Show file tree
Hide file tree
Showing 2 changed files with 1,023 additions and 84 deletions.
201 changes: 117 additions & 84 deletions ev3_scratch.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,49 +5,65 @@
// My bricks are named serialBrick1 (etc)
// Turn off the iPod/iPhone/iPad checkbox on the EV3 Bluetooth settings after pairing or else it will not work at all

function timeStamp()
{
return (new Date).toISOString().replace(/z|t/gi,' ').trim();
}

// scratchX is loading our javascript file again each time a saved SBX file is opened.
// JavaScript is weird and this causes our object to be reloaded and re-registered.
// Prevent this using global variable theEV3Device and EV3Connected that will only initialize to null the first time they are declared.
// This fixes a Windows bug where it would not reconnect.
var DEBUG_NO_EV3 = false;
var theEV3Device = theEV3Device || null;
var EV3ScratchAlreadyLoaded = EV3ScratchAlreadyLoaded || false;
var EV3Connected = EV3Connected || false;

(function(ext) {
// Cleanup function when the extension is unloaded
ext._shutdown = function() {};


ext._getStatus = function()
{
if (!connected)
if (!EV3Connected)
return { status:1, msg:'Disconnected' };
else
return { status:2, msg:'Connected' };
};

ext._deviceRemoved = function(dev)
{
console.log('Device removed');
console.log(timeStamp() +' Device removed');
// Not currently implemented with serial devices
};


var connected = false;
var connecting = false;
var notifyConnection = false;
var device = null;

var warnedAboutBattery = false;
var potentialDevices = [];
var deviceTimeout = 0;
ext._deviceConnected = function(dev) {

console.log(timeStamp() + '_deviceConnected: ' + dev.id);

// brick's serial port must be named like tty.serialBrick7-SerialPort
// this is how 10.10 is naming it automatically, the brick name being serialBrick7
// the Scratch plugin is only letting us know about serial ports with names that
// "begin with tty.usbmodem, tty.serial, or tty.usbserial" - according to khanning

if ((dev.id.indexOf('/dev/tty.serialBrick') === 0 && dev.id.indexOf('-SerialPort') != -1) || dev.id.indexOf('COM') === 0)

ext._deviceConnected = function(dev)
{
console.log(timeStamp() + '_deviceConnected: ' + dev.id);
if (EV3Connected)
{
console.log("Already EV3Connected. Ignoring");
}
// brick's serial port must be named like tty.serialBrick7-SerialPort
// this is how 10.10 is naming it automatically, the brick name being serialBrick7
// the Scratch plugin is only letting us know about serial ports with names that
// "begin with tty.usbmodem, tty.serial, or tty.usbserial" - according to khanning

if ((dev.id.indexOf('/dev/tty.serialBrick') === 0 && dev.id.indexOf('-SerialPort') != -1) || dev.id.indexOf('COM') === 0)
{

if (potentialDevices.filter(function(e) { return e.id == dev.id; }).length == 0) {
potentialDevices.push(dev); }
if (!deviceTimeout)
deviceTimeout = setTimeout(tryNextDevice, 1000);
}
if (potentialDevices.filter(function(e) { return e.id == dev.id; }).length == 0) {
potentialDevices.push(dev); }
if (!deviceTimeout)
deviceTimeout = setTimeout(tryNextDevice, 1000);
}
};

var poller = null;
Expand All @@ -57,32 +73,28 @@
var waitingForPing = false;
var waitingForInitialConnection = false;

var DEBUG_NO_EV3 = false;
var theDevice = null;

function clearSensorStatuses()
{
var numSensorBlocks = 9;
waitingQueries = [];
for (x = 0; x < numSensorBlocks; x++)
{
waitingCallbacks[x] = [];
global_touch_pressed[x] = false;
global_ir_button_pressed[x] = false;
global_sensor_result[x] = 0;
global_sensor_queried[x] = 0;
}
}

var counter = 0;

function reconnect()
{
{
clearSensorStatuses();
counter = 0;

theDevice.open({ stopBits: 0, bitRate: 57600 /*115200*/, ctsFlowControl: 0}); //, parity:2, bufferSize:255 });
console.log(timeStamp() + ': Attempting connection with ' + theDevice.id);
theDevice.set_receive_handler(receive_handler);
theEV3Device.open({ stopBits: 0, bitRate: 57600 /*115200*/, ctsFlowControl: 0}); //, parity:2, bufferSize:255 });
console.log(timeStamp() + ': Attempting connection with ' + theEV3Device.id);
theEV3Device.set_receive_handler(receive_handler);

connecting = true;
testTheConnection(startupBatteryCheckCallback);
Expand All @@ -96,11 +108,17 @@ function startupBatteryCheckCallback(result)

waitingForInitialConnection = false;

connected = true;
EV3Connected = true;
connecting = false;

playStartUpTones();

if (result < 11 && !warnedAboutBattery)
{
alert("Your battery is getting low.");
warnedAboutBattery = true;
}

// no watchdog right now. reconnection is too flakey so there is no point
// setupWatchdog();
}
Expand All @@ -112,11 +130,6 @@ function setupWatchdog()

poller = setInterval(pingBatteryWatchdog, 10000);
}

function timeStamp()
{
return (new Date).toISOString().replace(/z|t/gi,' ').trim();
}

function pingBatteryWatchdog()
{
Expand All @@ -134,7 +147,7 @@ function pingTimeOutCallback()
if (poller)
clearInterval(poller);

connected = false;
EV3Connected = false;

alert("The connection to the brick was lost. Check your brick and refresh the page to reconnect. (Don't forget to save your project first!)");
/* if (r == true) {
Expand Down Expand Up @@ -213,36 +226,30 @@ function playStartUpTones()
potentialDevices.sort((function(a, b){return b.id.localeCompare(a.id)}));

console.log("devices: " + potentialDevices);
device = potentialDevices.shift();
var device = potentialDevices.shift();
if (!device)
return;

theDevice = device;
theEV3Device = device;

if (!DEBUG_NO_EV3)
{
reconnect();
}
/*
watchdog = setTimeout(function() {
clearInterval(poller);
poller = null;
device.set_receive_handler(null);
device.close();
device = null;
tryNextDevice();
}, 5000);
*/
if (!DEBUG_NO_EV3)
{
reconnect();
}
}

ext._shutdown = function()
{
if (device && connected)
device.close();
console.log(timeStamp() +' SHUTDOWN: ' + theEV3Device.id);
/*
if (theEV3Device)
theEV3Device.close();
if (poller)
clearInterval(poller);

device = null;
EV3Connected = false;
theEV3Device = null;
*/

};

// create hex string from bytes
Expand All @@ -264,19 +271,21 @@ function playStartUpTones()

var waitingCallbacks = [[],[],[],[],[],[],[],[], []];
var waitingQueries = [];
var global_touch_pressed = [false, false, false, false,false, false, false, false, false];
var global_ir_button_pressed = [false, false, false, false,false, false, false, false, false];
var global_sensor_result = [0, 0, 0, 0, 0, 0, 0, 0, 0];
var global_sensor_queried = [0, 0, 0, 0, 0, 0, 0, 0, 0];

function receive_handler(data)
{
var inputData = new Uint8Array(data);
console.log("received: " + createHexString(inputData));
console.log(timeStamp() + " received: " + createHexString(inputData));

if (!(connected || connecting))
if (!(EV3Connected || connecting))
return;

var query_info = waitingQueries.shift();
if (!query_info)
return;

var this_is_from_port = query_info[0];
var mode = query_info[1];
var modeType = query_info[2];
Expand All @@ -302,12 +311,6 @@ function playStartUpTones()
else
theResult = "none";
}
/*
else if (modeType == COLOR_RAW_RGB) // is color_raw encoded as a string, hex, or number?
{
theResult = num; //maybe? probably not, but here's hoping it's this simple.
}
*/
}

else if (mode == IR_SENSOR)
Expand All @@ -333,9 +336,8 @@ function playStartUpTones()
}
}

global_touch_pressed[this_is_from_port] = theResult;
global_sensor_result[this_is_from_port] = theResult;
global_sensor_queried[this_is_from_port]--;
global_ir_button_pressed[this_is_from_port] = theResult;
while(callback = waitingCallbacks[this_is_from_port].shift())
{
console.log("result: " + theResult);
Expand Down Expand Up @@ -519,15 +521,15 @@ function playStartUpTones()

function sendCommand(commandArray)
{
if ((connected || connecting) && device)
device.send(commandArray.buffer);
if ((EV3Connected || connecting) && theEV3Device)
theEV3Device.send(commandArray.buffer);
}

ext.allMotorsOn = function(which, power)
{
clearDriveTimer();

console.log("motor " + which + " power: " + power);
console.log("motor " + which + " power: " + power);

motor(which, power);
}
Expand Down Expand Up @@ -699,22 +701,22 @@ function playFreqM2M(freq, duration)

ext.whenButtonPressed = function(port)
{
if (!device || !connected)
if (!theEV3Device || !EV3Connected)
return false;
var portInt = parseInt(port) - 1;
readTouchSensor(portInt);
return global_touch_pressed[portInt];
return global_sensor_result[portInt];
}

ext.whenRemoteButtonPressed = function(IRbutton, port)
{
if (!device || !connected)
if (!theEV3Device || !EV3Connected)
return false;

var portInt = parseInt(port) - 1;
readIRRemoteSensor(portInt);

return (global_ir_button_pressed[portInt] == IRbutton);
return (global_sensor_result[portInt] == IRbutton);
}

ext.readTouchSensorPort = function(port, callback)
Expand All @@ -733,15 +735,43 @@ function playFreqM2M(freq, duration)
if (mode == 'RGBcolor') { modeCode = COLOR_RAW_RGB; }

var portInt = parseInt(port) - 1;

waitingCallbacks[portInt].push(callback);
if (global_sensor_queried[portInt] == 0)
{
global_sensor_queried[portInt]++;
readFromSensor2(portInt, COLOR_SENSOR, modeCode);
}

readFromColorSensor(portInt, modeCode);
}

function readFromColorSensor(portInt, modeCode)
{
if (global_sensor_queried[portInt] == 0)
{
global_sensor_queried[portInt]++;
readFromSensor2(portInt, COLOR_SENSOR, modeCode);
}
}

var lineCheckingInterval = 0;

ext.waitUntilDarkLinePort = function(port, callback)
{
if (lineCheckingInterval)
clearInterval(lineCheckingInterval);
lineCheckingInterval = 0;
var modeCode = REFLECTED_INTENSITY;
var portInt = parseInt(port) - 1;
global_sensor_result[portInt] = -1;

lineCheckingInterval = window.setInterval(function()
{
readFromColorSensor(portInt, modeCode);
if (global_sensor_result[portInt] < 25 && global_sensor_result[portInt] >= 0) // darkness or just not reflection (air)
{
clearInterval(lineCheckingInterval);
lineCheckingInterval = 0;
callback();
}
}, 5);
}

ext.readGyroPort = function(mode, port, callback)
{
var modeCode = GYRO_ANGLE;
Expand Down Expand Up @@ -876,6 +906,7 @@ function playFreqM2M(freq, duration)
['w', 'play note %m.note duration %n ms', 'playTone', 'C5', 500],
['w', 'play frequency %n duration %n ms', 'playFreq', '262', 500],
['R', 'light sensor %m.whichInputPort %m.lightSensorMode', 'readColorSensorPort', '1', 'color'],
// ['w', 'wait until light sensor %m.whichInputPort detects black line', 'waitUntilDarkLinePort', '1'],
['R', 'measure distance %m.whichInputPort', 'readDistanceSensorPort', '1'],
['R', 'remote button %m.whichInputPort', 'readRemoteButtonPort', '1'],
// ['R', 'gyro %m.gyroMode %m.whichInputPort', 'readGyroPort', 'angle', '1'],
Expand All @@ -901,6 +932,8 @@ function playFreqM2M(freq, duration)

var serial_info = {type: 'serial'};
ScratchExtensions.register('EV3 Control', descriptor, ext, serial_info);
console.log('registered: ');
})({});
console.log("EV3ScratchAlreadyLoaded: " + EV3ScratchAlreadyLoaded);
EV3ScratchAlreadyLoaded = true;
console.log(timeStamp() + ' registered extension. theEV3Device:' + theEV3Device);
})({});

Loading

0 comments on commit bb30295

Please sign in to comment.