2015-03-24 00:33:19 -07:00
// scratch_ext.js
// Shane M. Clements, November 2013
// ScratchExtensions
//
// Scratch 2.0 extension manager which Scratch communicates with to initialize extensions and communicate with them.
// The extension manager also handles creating the browser plugin to enable access to HID and serial devices.
2015-07-23 15:45:28 -04:00
window . ScratchExtensions = new ( function ( ) {
2015-03-24 00:33:19 -07:00
var plugin = null ;
var handlers = { } ;
var blockDefs = { } ;
var menuDefs = { } ;
var deviceSpecs = { } ;
var devices = { } ;
var poller = null ;
var lib = this ;
2016-08-02 00:49:34 -07:00
var isOffline = Scratch && Scratch . FlashApp && Scratch . FlashApp . ASobj &&
Scratch . FlashApp . ASobj . isOffline && Scratch . FlashApp . ASobj . isOffline ( ) ;
2015-07-23 15:45:28 -04:00
var pluginAvailable = function ( ) {
return ! ! window . ArrayBuffer && ! ! (
isOffline ||
( window . ScratchPlugin && window . ScratchPlugin . isAvailable ( ) ) ||
( window . ScratchDeviceHost && window . ScratchDeviceHost . isAvailable ( ) )
) ;
} ;
lib . register = function ( name , descriptor , handler , deviceSpec ) {
if ( name in handlers ) {
console . log ( 'Scratch extension "' + name + '" already exists!' ) ;
2015-03-24 00:33:19 -07:00
return false ;
}
handlers [ name ] = handler ;
blockDefs [ name ] = descriptor . blocks ;
2015-07-23 15:45:28 -04:00
if ( descriptor . menus ) menuDefs [ name ] = descriptor . menus ;
if ( deviceSpec ) deviceSpecs [ name ] = deviceSpec ;
2015-03-24 00:33:19 -07:00
// Show the blocks in Scratch!
var extObj = {
extensionName : name ,
blockSpecs : descriptor . blocks ,
url : descriptor . url ,
menus : descriptor . menus ,
javascriptURL : loadingURL
} ;
Scratch . FlashApp . ASobj . ASloadExtension ( extObj ) ;
2015-08-07 14:20:38 -07:00
2016-08-02 00:49:34 -07:00
if ( deviceSpec ) {
if ( ! plugin ) {
if ( pluginAvailable ( ) ) {
// createDevicePlugin() will eventually call checkPolling() if it succeeds
setTimeout ( createDevicePlugin , 10 ) ;
} else if ( ScratchDeviceManager ) {
// No plugin is NBD if we're using the SDM
checkPolling ( ) ;
} else if ( window . ScratchPlugin . useActiveX ) {
JSsetProjectBanner ( 'Sorry, your version of Internet Explorer is not supported. Please upgrade to version 10 or 11.' ) ;
}
}
else {
// Second hardware-using project in the same tab
checkPolling ( ) ;
}
}
2015-08-07 14:20:38 -07:00
2015-03-24 00:33:19 -07:00
return true ;
} ;
var loadingURL ;
2015-07-23 15:45:28 -04:00
lib . loadExternalJS = function ( url ) {
2015-03-24 00:33:19 -07:00
var scr = document . createElement ( "script" ) ;
scr . src = url ; // + "?ts=" + new Date().getTime();
loadingURL = url ;
document . getElementsByTagName ( "head" ) [ 0 ] . appendChild ( scr ) ;
} ;
2015-07-23 15:45:28 -04:00
lib . loadLocalJS = function ( code ) {
2015-03-24 00:33:19 -07:00
// Run the extension code in the global scope
try {
( new Function ( code ) ) ( ) ;
2015-07-23 15:45:28 -04:00
} catch ( e ) {
2015-03-24 00:33:19 -07:00
console . log ( e . stack . toString ( ) ) ;
}
} ;
2015-07-23 15:45:28 -04:00
lib . unregister = function ( name ) {
2016-08-02 00:49:34 -07:00
try {
handlers [ name ] . _shutdown ( ) ;
} catch ( e ) {
}
2015-03-24 00:33:19 -07:00
delete handlers [ name ] ;
delete blockDefs [ name ] ;
delete menuDefs [ name ] ;
delete deviceSpecs [ name ] ;
} ;
2016-08-02 00:49:34 -07:00
lib . canAccessDevices = function ( ) {
return pluginAvailable ( ) ;
} ;
2015-07-23 15:45:28 -04:00
lib . getReporter = function ( ext _name , reporter , args ) {
2015-03-24 00:33:19 -07:00
return handlers [ ext _name ] [ reporter ] . apply ( handlers [ ext _name ] , args ) ;
} ;
2015-07-23 15:45:28 -04:00
lib . getReporterAsync = function ( ext _name , reporter , args , job _id ) {
var callback = function ( retval ) {
2015-03-24 00:33:19 -07:00
Scratch . FlashApp . ASobj . ASextensionReporterDone ( ext _name , job _id , retval ) ;
2016-08-02 00:49:34 -07:00
} ;
2016-10-07 12:09:17 -07:00
if ( handlers [ ext _name ] . _getStatus ( ) . status != 2 ) {
callback ( false ) ;
}
else {
args . push ( callback ) ;
handlers [ ext _name ] [ reporter ] . apply ( handlers [ ext _name ] , args ) ;
}
2015-03-24 00:33:19 -07:00
} ;
2015-07-23 15:45:28 -04:00
lib . getReporterForceAsync = function ( ext _name , reporter , args , job _id ) {
var retval = handlers [ ext _name ] [ reporter ] . apply ( handlers [ ext _name ] , args ) ;
Scratch . FlashApp . ASobj . ASextensionReporterDone ( ext _name , job _id , retval ) ;
} ;
lib . runCommand = function ( ext _name , command , args ) {
2015-03-24 00:33:19 -07:00
handlers [ ext _name ] [ command ] . apply ( handlers [ ext _name ] , args ) ;
} ;
2015-07-23 15:45:28 -04:00
lib . runAsync = function ( ext _name , command , args , job _id ) {
var callback = function ( ) {
2015-03-24 00:33:19 -07:00
Scratch . FlashApp . ASobj . ASextensionCallDone ( ext _name , job _id ) ;
2016-08-02 00:49:34 -07:00
} ;
2015-03-24 00:33:19 -07:00
args . push ( callback ) ;
handlers [ ext _name ] [ command ] . apply ( handlers [ ext _name ] , args ) ;
} ;
2015-07-23 15:45:28 -04:00
lib . getStatus = function ( ext _name ) {
2016-08-02 00:49:34 -07:00
if ( ! ( ext _name in handlers ) ) {
return { status : 0 , msg : 'Not loaded' } ;
}
2015-03-24 00:33:19 -07:00
2016-08-02 00:49:34 -07:00
if ( ext _name in deviceSpecs ) {
switch ( deviceSpecs [ ext _name ] . type ) {
2016-10-07 12:09:17 -07:00
case 'ble' :
2016-08-02 00:49:34 -07:00
case 'wedo2' :
2016-10-07 12:09:17 -07:00
if ( ! ( ScratchDeviceManager && ScratchDeviceManager . isConnected ( ) ) ) {
2016-08-02 00:49:34 -07:00
return { status : 0 , msg : 'Missing Scratch Device Manager' } ;
}
break ;
default :
if ( ! pluginAvailable ( ) ) {
return { status : 0 , msg : 'Missing browser plugin' } ;
}
break ;
}
}
2015-03-24 00:33:19 -07:00
return handlers [ ext _name ] . _getStatus ( ) ;
} ;
2016-08-02 00:49:34 -07:00
lib . stop = function ( ext _name ) {
var ext = handlers [ ext _name ] ;
if ( ext . _stop ) {
ext . _stop ( ) ;
}
else if ( ext . resetAll ) { // old, undocumented call
ext . resetAll ( ) ;
}
} ;
2015-07-23 15:45:28 -04:00
lib . notify = function ( text ) {
2016-08-02 00:49:34 -07:00
if ( window . JSsetProjectBanner ) {
JSsetProjectBanner ( text ) ;
} else {
alert ( text ) ;
}
2015-03-24 00:33:19 -07:00
} ;
2015-07-23 15:45:28 -04:00
lib . resetPlugin = function ( ) {
2015-03-24 00:33:19 -07:00
if ( plugin && plugin . reset ) plugin . reset ( ) ;
shutdown ( ) ;
} ;
2015-07-23 15:45:28 -04:00
$ ( window ) . unload ( function ( e ) {
2015-03-24 00:33:19 -07:00
shutdown ( ) ;
} ) ;
function shutdown ( ) {
2016-08-02 00:49:34 -07:00
for ( var extName in handlers ) {
2015-03-24 00:33:19 -07:00
handlers [ extName ] . _shutdown ( ) ;
2016-08-02 00:49:34 -07:00
}
2015-03-24 00:33:19 -07:00
handlers = { } ;
stopPolling ( ) ;
}
function checkDevices ( ) {
var awaitingSpecs = { } ;
2016-08-02 00:49:34 -07:00
var ext _name ;
for ( ext _name in deviceSpecs ) {
2015-07-23 15:45:28 -04:00
if ( ! devices [ ext _name ] ) {
2015-03-24 00:33:19 -07:00
var spec = deviceSpecs [ ext _name ] ;
2015-07-23 15:45:28 -04:00
if ( spec . type == 'hid' ) {
if ( ! awaitingSpecs [ 'hid' ] ) awaitingSpecs [ 'hid' ] = { } ;
2015-03-24 00:33:19 -07:00
awaitingSpecs [ 'hid' ] [ spec . vendor + '_' + spec . product ] = ext _name ;
}
2016-10-07 12:09:17 -07:00
else {
awaitingSpecs [ spec . type ] = ext _name ;
2016-08-02 00:49:34 -07:00
}
2015-03-24 00:33:19 -07:00
}
2016-08-02 00:49:34 -07:00
}
2015-03-24 00:33:19 -07:00
2016-10-07 12:09:17 -07:00
for ( var specType in awaitingSpecs ) {
if ( ! awaitingSpecs . hasOwnProperty ( specType ) ) continue ;
if ( plugin && specType == 'hid' ) {
var awaitingHid = awaitingSpecs [ 'hid' ] ;
2016-08-02 00:49:34 -07:00
plugin . hid _list ( function ( deviceList ) {
for ( var i = 0 ; i < deviceList . length ; i ++ ) {
2016-10-07 12:09:17 -07:00
var deviceID = deviceList [ i ] [ "vendor_id" ] + '_' + deviceList [ i ] [ "product_id" ] ;
var hid _ext _name = awaitingHid [ deviceID ] ;
if ( hid _ext _name ) {
handlers [ hid _ext _name ] . _deviceConnected ( new HidDevice ( deviceList [ i ] , hid _ext _name ) ) ;
2016-08-02 00:49:34 -07:00
}
}
} ) ;
}
2016-10-07 12:09:17 -07:00
else if ( plugin && specType == 'serial' ) {
2016-08-02 00:49:34 -07:00
ext _name = awaitingSpecs [ 'serial' ] ;
plugin . serial _list ( function ( deviceList ) {
for ( var i = 0 ; i < deviceList . length ; i ++ ) {
handlers [ ext _name ] . _deviceConnected ( new SerialDevice ( deviceList [ i ] , ext _name ) ) ;
}
} ) ;
}
2016-10-07 12:09:17 -07:00
else if ( ScratchDeviceManager ) {
ext _name = awaitingSpecs [ specType ] ;
ScratchDeviceManager . device _list ( specType , ext _name , deviceSpecs [ ext _name ] , deviceListCallback ) ;
}
2015-03-24 00:33:19 -07:00
}
2016-08-02 00:49:34 -07:00
if ( ! shouldLookForDevices ( ) ) {
2015-03-24 00:33:19 -07:00
stopPolling ( ) ;
2016-08-02 00:49:34 -07:00
}
2015-03-24 00:33:19 -07:00
}
2016-10-07 12:09:17 -07:00
function deviceListCallback ( deviceList , ext _type , ext _name ) {
for ( var i = 0 ; i < deviceList . length ; ++ i ) {
var deviceConstructor = Devices [ ext _type ] ;
var deviceId = deviceList [ i ] . id || deviceList [ i ] ;
var device = new deviceConstructor ( deviceId , ext _type , ext _name ) ;
handlers [ ext _name ] . _deviceConnected ( device ) ;
}
}
2015-03-24 00:33:19 -07:00
function checkPolling ( ) {
2015-07-23 15:45:28 -04:00
if ( poller || ! shouldLookForDevices ( ) ) return ;
2015-03-24 00:33:19 -07:00
poller = setInterval ( checkDevices , 500 ) ;
2015-07-23 15:45:28 -04:00
}
2015-03-24 00:33:19 -07:00
function stopPolling ( ) {
2015-07-23 15:45:28 -04:00
if ( poller ) clearInterval ( poller ) ;
2015-03-24 00:33:19 -07:00
poller = null ;
}
function shouldLookForDevices ( ) {
2016-08-02 00:49:34 -07:00
for ( var ext _name in deviceSpecs ) {
if ( ! devices [ ext _name ] ) {
2015-03-24 00:33:19 -07:00
return true ;
2016-08-02 00:49:34 -07:00
}
}
2015-03-24 00:33:19 -07:00
return false ;
}
function createDevicePlugin ( ) {
2015-07-23 15:45:28 -04:00
if ( plugin ) return ;
2016-10-07 12:09:17 -07:00
try {
// TODO: delegate more of this to the other files
if ( isOffline ) {
// Talk to the AIR Native Extension through the offline editor's plugin emulation.
plugin = Scratch . FlashApp . ASobj . getPlugin ( ) ;
} else if ( window . ScratchDeviceHost && window . ScratchDeviceHost . isAvailable ( ) ) {
// Talk to the Native Messaging Host through a Chrome extension.
plugin = window . ScratchDeviceHost ;
2015-07-23 15:45:28 -04:00
} else {
2016-10-07 12:09:17 -07:00
if ( window . ScratchPlugin . useActiveX ) {
// we must be on IE or similar
plugin = new ActiveXObject ( window . ScratchPlugin . axObjectName ) ;
} else {
// Not IE: try NPAPI
var pluginContainer = document . createElement ( 'div' ) ;
document . getElementById ( 'scratch' ) . parentNode . appendChild ( pluginContainer ) ;
pluginContainer . innerHTML =
'<object type="application/x-scratchdeviceplugin" width="1" height="1"> </object>' ;
plugin = pluginContainer . firstChild ;
}
// Talk to the actual plugin, but make it pretend to be asynchronous.
plugin = new window . ScratchPlugin . PluginWrapper ( plugin ) ;
2015-07-23 15:45:28 -04:00
}
2016-10-07 12:09:17 -07:00
}
catch ( e ) {
console . error ( 'Error creating plugin or wrapper:' , e ) ;
plugin = null ;
2015-07-23 15:45:28 -04:00
}
2015-03-24 00:33:19 -07:00
2015-07-23 15:45:28 -04:00
// Wait a moment to access the plugin and claim any devices that plugins are
// interested in.
setTimeout ( checkPolling , 100 ) ;
2015-03-24 00:33:19 -07:00
}
2016-08-02 00:49:34 -07:00
function HidDevice ( info , ext _name ) {
2015-03-24 00:33:19 -07:00
var dev = null ;
var self = this ;
// TODO: add support for multiple devices per extension
//if(!(ext_name in devices)) devices[ext_name] = {};
this . id = info [ "path" ] ;
this . info = info ;
function disconnect ( ) {
2015-07-23 15:45:28 -04:00
setTimeout ( function ( ) {
2015-03-24 00:33:19 -07:00
self . close ( ) ;
handlers [ ext _name ] . _deviceRemoved ( self ) ;
} , 0 ) ;
}
2015-07-23 15:45:28 -04:00
this . open = function ( readyCallback ) {
2015-08-07 14:20:38 -07:00
plugin . hid _open ( self . id , function ( d ) {
dev = d ;
2016-08-02 00:49:34 -07:00
if ( dev ) {
devices [ ext _name ] = self ;
dev . set _nonblocking ( true ) ;
}
if ( readyCallback ) readyCallback ( d ? self : null ) ;
2015-08-07 14:20:38 -07:00
} ) ;
2015-03-24 00:33:19 -07:00
} ;
2015-07-23 15:45:28 -04:00
this . close = function ( ) {
if ( ! dev ) return ;
2015-03-24 00:33:19 -07:00
dev . close ( ) ;
delete devices [ ext _name ] ;
dev = null ;
checkPolling ( ) ;
} ;
2015-07-23 15:45:28 -04:00
this . write = function ( data , callback ) {
if ( ! dev ) return ;
dev . write ( data , function ( len ) {
if ( len < 0 ) disconnect ( ) ;
if ( callback ) callback ( len ) ;
} ) ;
2015-03-24 00:33:19 -07:00
} ;
2015-07-23 15:45:28 -04:00
this . read = function ( callback , len ) {
if ( ! dev ) return null ;
if ( ! len ) len = 65 ;
dev . read ( len , function ( data ) {
if ( data . byteLength == 0 ) disconnect ( ) ;
callback ( data ) ;
} ) ;
2015-03-24 00:33:19 -07:00
} ;
}
2016-08-02 00:49:34 -07:00
function SerialDevice ( id , ext _name ) {
2015-03-24 00:33:19 -07:00
var dev = null ;
var self = this ;
// TODO: add support for multiple devices per extension
//if(!(ext_name in devices)) devices[ext_name] = {};
this . id = id ;
2015-07-23 15:45:28 -04:00
this . open = function ( opts , readyCallback ) {
2016-08-02 00:49:34 -07:00
plugin . serial _open ( self . id , opts , function ( d ) {
dev = d ;
if ( dev ) {
2015-08-07 14:20:38 -07:00
devices [ ext _name ] = self ;
2015-07-23 15:45:28 -04:00
dev . set _error _handler ( function ( message ) {
2016-09-13 14:30:35 -04:00
console . log ( 'Serial device error\nDevice: ' + id + '\nError: ' + message ) ;
2015-07-23 15:45:28 -04:00
} ) ;
2016-08-02 00:49:34 -07:00
}
if ( readyCallback ) readyCallback ( d ? self : null ) ;
} ) ;
2015-03-24 00:33:19 -07:00
} ;
2015-07-23 15:45:28 -04:00
this . close = function ( ) {
if ( ! dev ) return ;
2015-03-24 00:33:19 -07:00
dev . close ( ) ;
delete devices [ ext _name ] ;
dev = null ;
checkPolling ( ) ;
} ;
2015-07-23 15:45:28 -04:00
this . send = function ( data ) {
if ( ! dev ) return ;
2015-03-24 00:33:19 -07:00
dev . send ( data ) ;
} ;
2015-07-23 15:45:28 -04:00
this . set _receive _handler = function ( handler ) {
if ( ! dev ) return ;
2015-03-24 00:33:19 -07:00
dev . set _receive _handler ( handler ) ;
} ;
}
2016-08-02 00:49:34 -07:00
2016-10-07 12:09:17 -07:00
function WeDo2Device ( id , ext _type , ext _name ) {
2016-08-02 00:49:34 -07:00
var dev = null ;
2016-10-07 12:09:17 -07:00
this . ext _type = ext _type ;
this . ext _name = ext _name ;
2016-08-02 00:49:34 -07:00
var self = this ;
this . id = id ;
2016-10-07 12:09:17 -07:00
function RawWeDo2 ( deviceId , socket ) {
var WeDo = this ;
var eventHandlers = { } ;
WeDo . close = function ( ) {
socket . close ( ) ;
} ;
WeDo . setMotorOn = function ( motorIndex , power ) {
socket . emit ( 'motorOn' , { motorIndex : motorIndex , power : power } ) ;
} ;
WeDo . setMotorOff = function ( motorIndex ) {
socket . emit ( 'motorOff' , { motorIndex : motorIndex } ) ;
} ;
WeDo . setMotorBrake = function ( motorIndex ) {
socket . emit ( 'motorBrake' , { motorIndex : motorIndex } ) ;
} ;
WeDo . setLED = function ( rgb ) {
socket . emit ( 'setLED' , { rgb : rgb } ) ;
} ;
WeDo . playTone = function ( tone , durationMs ) {
socket . emit ( 'playTone' , { tone : tone , ms : durationMs } ) ;
} ;
WeDo . stopTone = function ( ) {
socket . emit ( 'stopTone' ) ;
} ;
function setHandler ( eventName , handler ) {
if ( eventHandlers . hasOwnProperty ( eventName ) ) {
var oldHandler = eventHandlers [ eventName ] ;
if ( oldHandler ) {
socket . removeListener ( eventName , oldHandler ) ;
}
}
if ( handler ) {
socket . on ( eventName , handler ) ;
}
eventHandlers [ eventName ] = handler ;
}
// function handler(event) { access event.sensorName and event.sensorValue }
WeDo . setSensorHandler = function ( handler ) {
setHandler ( 'sensorChanged' , handler ) ;
} ;
WeDo . setDeviceWasClosedHandler = function ( handler ) {
// TODO: resolve this ambiguity
setHandler ( 'disconnect' , handler ) ;
setHandler ( 'deviceWasClosed' , handler ) ;
} ;
}
2016-08-02 00:49:34 -07:00
function disconnect ( ) {
setTimeout ( function ( ) {
self . close ( ) ;
handlers [ ext _name ] . _deviceRemoved ( self ) ;
} , 0 ) ;
}
2016-10-07 12:09:17 -07:00
this . is _open = function ( ) {
return ! ! dev ;
} ;
2016-08-02 00:49:34 -07:00
this . open = function ( readyCallback ) {
2016-10-07 12:09:17 -07:00
ScratchDeviceManager . socket _open ( self . ext _name , self . ext _type , self . id , function ( socket ) {
if ( socket ) {
dev = new RawWeDo2 ( self . id , socket ) ;
2016-08-02 00:49:34 -07:00
devices [ ext _name ] = self ;
dev . setDeviceWasClosedHandler ( disconnect ) ;
}
2016-10-07 12:09:17 -07:00
else {
dev = null ;
disconnect ( ) ;
}
if ( readyCallback ) {
readyCallback ( dev ? self : null ) ;
}
2016-08-02 00:49:34 -07:00
} ) ;
} ;
2016-10-07 12:09:17 -07:00
2016-08-02 00:49:34 -07:00
this . close = function ( ) {
if ( ! dev ) return ;
dev . close ( ) ;
delete devices [ ext _name ] ;
dev = null ;
checkPolling ( ) ;
} ;
// The `handler` should be a function like: function handler(event) {...}
// The `event` will contain properties called `sensorName` and `sensorValue`.
// Sensor names include `tilt` and `distance`.
this . set _sensor _handler = function ( handler ) {
if ( ! dev ) return ;
dev . setSensorHandler ( handler ) ;
} ;
// Starts motor at given power, 0-100. Use negative power for reverse.
this . set _motor _on = function ( motorIndex , power ) {
dev . setMotorOn ( motorIndex , power ) ;
} ;
// Applies active braking.
this . set _motor _brake = function ( motorIndex ) {
dev . setMotorBrake ( motorIndex ) ;
} ;
// Turns motor off. Depending on power and load, the motor will drift to a stop.
this . set _motor _off = function ( motorIndex ) {
dev . setMotorOff ( motorIndex ) ;
} ;
// Sets the RGB LED color. The RGB color should be specified in 0xRRGGBB format.
this . set _led = function ( rgb ) {
dev . setLED ( rgb ) ;
} ;
this . play _tone = function ( tone , durationMs ) {
dev . playTone ( tone , durationMs ) ;
} ;
this . stop _tone = function ( ) {
dev . stopTone ( ) ;
} ;
}
2016-10-07 12:09:17 -07:00
function BleDevice ( id , ext _type , ext _name ) {
var self = this ;
this . ext _name = ext _name ;
this . ext _type = ext _type ;
this . socket = null ;
this . id = id ;
var onActions = [ ] ;
var onceActions = [ ] ;
function disconnect ( ) {
setTimeout ( function ( ) {
self . close ( ) ;
handlers [ self . ext _name ] . _deviceRemoved ( self ) ;
} , 0 ) ;
}
this . emit = function ( action , data ) {
if ( self . socket ) {
self . socket . emit ( action , data ) ;
}
return ! ! self . socket ;
} ;
this . on = function ( action , callback ) {
if ( self . is _open ( ) ) {
self . socket . on ( action , callback ) ;
}
else {
onActions . push ( [ action , callback ] ) ;
}
} ;
this . once = function ( action , callback ) {
if ( self . is _open ( ) ) {
self . socket . once ( action , callback ) ;
}
else {
onceActions . push ( [ action , callback ] ) ;
}
} ;
this . open = function ( readyCallback ) {
ScratchDeviceManager . socket _open ( self . ext _name , ext _type , self . id , function ( s ) {
self . socket = s ;
if ( self . socket ) {
devices [ self . ext _name ] = self ;
onActions . forEach ( function ( element ) {
self . socket . on ( element [ 0 ] , element [ 1 ] ) ;
} ) ;
onceActions . forEach ( function ( element ) {
self . socket . once ( element [ 0 ] , element [ 1 ] ) ;
} ) ;
self . socket . on ( 'disconnect' , disconnect ) ;
self . socket . on ( 'deviceWasClosed' , disconnect ) ;
}
if ( readyCallback ) readyCallback ( self . socket ? self : null ) ;
} ) ;
} ;
this . close = function ( ) {
if ( ! self . socket ) return ;
self . socket . close ( ) ;
delete devices [ self . ext _name ] ;
self . socket = null ;
checkPolling ( ) ;
} ;
this . is _open = function ( ) {
return ! ! self . socket ;
} ;
}
Devices = { ble : BleDevice , wedo2 : WeDo2Device } ;
2015-03-24 00:33:19 -07:00
} ) ( ) ;