2015-02-26 15:47:56 +00:00
( function ( ) {
2015-08-31 21:39:48 +00:00
var Promise , _ , async , capitano , commandOptions , deviceConfig , events , form , helpers , htmlToText , image , inject , manager , pine , registerDevice , resin , vcs , visuals ;
2015-08-14 18:11:49 +00:00
Promise = require ( 'bluebird' ) ;
2015-05-05 20:32:44 +00:00
capitano = require ( 'capitano' ) ;
2015-02-26 15:47:56 +00:00
2015-08-12 12:17:46 +00:00
_ = require ( 'lodash' ) ;
2015-02-26 15:47:56 +00:00
async = require ( 'async' ) ;
resin = require ( 'resin-sdk' ) ;
visuals = require ( 'resin-cli-visuals' ) ;
2015-03-12 16:03:59 +00:00
vcs = require ( 'resin-vcs' ) ;
2015-05-18 13:34:40 +00:00
manager = require ( 'resin-image-manager' ) ;
image = require ( 'resin-image' ) ;
inject = require ( 'resin-config-inject' ) ;
2015-06-04 12:55:32 +00:00
registerDevice = require ( 'resin-register-device' ) ;
pine = require ( 'resin-pine' ) ;
2015-07-22 22:06:53 +00:00
deviceConfig = require ( 'resin-device-config' ) ;
2015-07-27 12:08:55 +00:00
form = require ( 'resin-cli-form' ) ;
2015-08-31 21:39:48 +00:00
events = require ( 'resin-cli-events' ) ;
2015-05-07 15:40:12 +00:00
htmlToText = require ( 'html-to-text' ) ;
2015-08-17 13:49:59 +00:00
helpers = require ( '../utils/helpers' ) ;
2015-02-26 15:47:56 +00:00
commandOptions = require ( './command-options' ) ;
exports . list = {
signature : 'devices' ,
description : 'list all devices' ,
2015-04-27 15:20:53 +00:00
help : 'Use this command to list all devices that belong to you.\n\nYou can filter the devices by application by using the `--application` option.\n\nExamples:\n\n $ resin devices\n $ resin devices --application MyApp\n $ resin devices --app MyApp\n $ resin devices -a MyApp' ,
options : [ commandOptions . optionalApplication ] ,
2015-02-26 15:47:56 +00:00
permission : 'user' ,
action : function ( params , options , done ) {
2015-08-17 13:49:59 +00:00
return Promise [ "try" ] ( function ( ) {
if ( options . application != null ) {
return resin . models . device . getAllByApplication ( options . application ) ;
2015-02-26 15:47:56 +00:00
}
2015-08-17 13:49:59 +00:00
return resin . models . device . getAll ( ) ;
} ) . tap ( function ( devices ) {
return console . log ( visuals . table . horizontal ( devices , [ 'id' , 'name' , 'device_type' , 'is_online' , 'application_name' , 'status' , 'last_seen' ] ) ) ;
} ) . nodeify ( done ) ;
2015-02-26 15:47:56 +00:00
}
} ;
exports . info = {
2015-07-22 22:06:53 +00:00
signature : 'device <uuid>' ,
2015-02-26 15:47:56 +00:00
description : 'list a single device' ,
2015-07-22 22:06:53 +00:00
help : 'Use this command to show information about a single device.\n\nExamples:\n\n $ resin device 7cf02a62a3a84440b1bb5579a3d57469148943278630b17e7fc6c4f7b465c9' ,
2015-02-26 15:47:56 +00:00
permission : 'user' ,
action : function ( params , options , done ) {
2015-07-22 22:06:53 +00:00
return resin . models . device . get ( params . uuid ) . then ( function ( device ) {
2015-07-09 13:56:17 +00:00
if ( device . last _seen == null ) {
device . last _seen = 'Not seen' ;
}
2015-08-31 21:39:48 +00:00
console . log ( visuals . table . vertical ( device , [ "$" + device . name + "$" , 'id' , 'device_type' , 'is_online' , 'ip_address' , 'application_name' , 'status' , 'last_seen' , 'uuid' , 'commit' , 'supervisor_version' , 'is_web_accessible' , 'note' ] ) ) ;
return events . send ( 'device.open' , {
device : device . uuid
} ) ;
2015-07-22 22:06:53 +00:00
} ) . nodeify ( done ) ;
2015-02-26 15:47:56 +00:00
}
} ;
exports . remove = {
2015-07-22 22:06:53 +00:00
signature : 'device rm <uuid>' ,
2015-02-26 15:47:56 +00:00
description : 'remove a device' ,
2015-07-22 22:06:53 +00:00
help : 'Use this command to remove a device from resin.io.\n\nNotice this command asks for confirmation interactively.\nYou can avoid this by passing the `--yes` boolean option.\n\nExamples:\n\n $ resin device rm 7cf02a62a3a84440b1bb5579a3d57469148943278630b17e7fc6c4f7b465c9\n $ resin device rm 7cf02a62a3a84440b1bb5579a3d57469148943278630b17e7fc6c4f7b465c9 --yes' ,
2015-02-26 15:47:56 +00:00
options : [ commandOptions . yes ] ,
permission : 'user' ,
action : function ( params , options , done ) {
2015-08-20 20:16:20 +00:00
return helpers . confirm ( options . yes , 'Are you sure you want to delete the device?' ) . then ( function ( ) {
2015-08-17 13:49:59 +00:00
return resin . models . device . remove ( params . uuid ) ;
2015-08-31 21:39:48 +00:00
} ) . tap ( function ( ) {
return events . send ( 'device.delete' , {
device : params . uuid
} ) ;
2015-08-17 13:49:59 +00:00
} ) . nodeify ( done ) ;
2015-02-26 15:47:56 +00:00
}
} ;
exports . identify = {
signature : 'device identify <uuid>' ,
description : 'identify a device with a UUID' ,
2015-03-03 14:14:16 +00:00
help : 'Use this command to identify a device.\n\nIn the Raspberry Pi, the ACT led is blinked several times.\n\nExamples:\n\n $ resin device identify 23c73a12e3527df55c60b9ce647640c1b7da1b32d71e6a39849ac0f00db828' ,
2015-02-26 15:47:56 +00:00
permission : 'user' ,
action : function ( params , options , done ) {
2015-07-22 22:06:53 +00:00
return resin . models . device . identify ( params . uuid ) . nodeify ( done ) ;
2015-02-26 15:47:56 +00:00
}
} ;
exports . rename = {
2015-07-22 22:06:53 +00:00
signature : 'device rename <uuid> [newName]' ,
2015-02-26 15:47:56 +00:00
description : 'rename a resin device' ,
2015-07-22 22:06:53 +00:00
help : 'Use this command to rename a device.\n\nIf you omit the name, you\'ll get asked for it interactively.\n\nExamples:\n\n $ resin device rename 7cf02a62a3a84440b1bb5579a3d57469148943278630b17e7fc6c4f7b465c9 MyPi\n $ resin device rename 7cf02a62a3a84440b1bb5579a3d57469148943278630b17e7fc6c4f7b465c9' ,
2015-02-26 15:47:56 +00:00
permission : 'user' ,
action : function ( params , options , done ) {
2015-08-17 13:49:59 +00:00
return Promise [ "try" ] ( function ( ) {
if ( ! _ . isEmpty ( params . newName ) ) {
return params . newName ;
2015-02-26 15:47:56 +00:00
}
2015-08-17 13:49:59 +00:00
return form . ask ( {
message : 'How do you want to name this device?' ,
type : 'input'
} ) ;
2015-08-31 21:39:48 +00:00
} ) . then ( _ . partial ( resin . models . device . rename , params . uuid ) ) . tap ( function ( ) {
return events . send ( 'device.rename' , {
device : params . uuid
} ) ;
} ) . nodeify ( done ) ;
2015-02-26 15:47:56 +00:00
}
} ;
exports . init = {
signature : 'device init [device]' ,
description : 'initialise a device with resin os' ,
2015-05-18 13:34:40 +00:00
help : 'Use this command to download the OS image of a certain application and write it to an SD Card.\n\nNote that this command requires admin privileges.\n\nIf `device` is omitted, you will be prompted to select a device interactively.\n\nNotice this command asks for confirmation interactively.\nYou can avoid this by passing the `--yes` boolean option.\n\nYou can quiet the progress bar and other logging information by passing the `--quiet` boolean option.\n\nYou need to configure the network type and other settings:\n\nEthernet:\n You can setup the device OS to use ethernet by setting the `--network` option to "ethernet".\n\nWifi:\n You can setup the device OS to use wifi by setting the `--network` option to "wifi".\n If you set "network" to "wifi", you will need to specify the `--ssid` and `--key` option as well.\n\nYou can omit network related options to be asked about them interactively.\n\nExamples:\n\n $ resin device init\n $ resin device init --application MyApp\n $ resin device init --application MyApp --network ethernet\n $ resin device init /dev/disk2 --application MyApp --network wifi --ssid MyNetwork --key secret' ,
2015-03-12 16:03:59 +00:00
options : [ commandOptions . optionalApplication , commandOptions . network , commandOptions . wifiSsid , commandOptions . wifiKey ] ,
2015-02-26 15:47:56 +00:00
permission : 'user' ,
2015-05-18 13:34:40 +00:00
root : true ,
2015-02-26 15:47:56 +00:00
action : function ( params , options , done ) {
2015-05-18 13:34:40 +00:00
var networkOptions ;
networkOptions = {
network : options . network ,
wifiSsid : options . ssid ,
wifiKey : options . key
} ;
2015-02-26 15:47:56 +00:00
return async . waterfall ( [
function ( callback ) {
2015-03-12 16:03:59 +00:00
if ( options . application != null ) {
return callback ( null , options . application ) ;
}
2015-07-10 17:04:17 +00:00
return vcs . getApplicationName ( process . cwd ( ) ) . nodeify ( callback ) ;
2015-04-20 13:13:15 +00:00
} , function ( applicationName , callback ) {
2015-05-18 13:34:40 +00:00
options . application = applicationName ;
2015-07-22 22:06:53 +00:00
return resin . models . application . has ( options . application ) . nodeify ( callback ) ;
2015-06-08 16:31:17 +00:00
} , function ( hasApplication , callback ) {
if ( ! hasApplication ) {
return callback ( new Error ( "Invalid application: " + options . application ) ) ;
}
2015-02-26 15:47:56 +00:00
if ( params . device != null ) {
return callback ( null , params . device ) ;
}
2015-08-20 15:53:10 +00:00
return form . ask ( {
type : 'drive' ,
message : 'Select a drive'
} ) . nodeify ( callback ) ;
2015-02-26 15:47:56 +00:00
} , function ( device , callback ) {
2015-03-23 22:32:18 +00:00
var message ;
2015-02-26 15:47:56 +00:00
params . device = device ;
2015-03-23 22:32:18 +00:00
message = "This will completely erase " + params . device + ". Are you sure you want to continue?" ;
2015-07-27 12:08:55 +00:00
if ( options . yes ) {
return callback ( null , true ) ;
} else {
return form . ask ( {
message : message ,
type : 'confirm' ,
"default" : false
} ) . nodeify ( callback ) ;
}
2015-02-26 15:47:56 +00:00
} , function ( confirmed , callback ) {
if ( ! confirmed ) {
return done ( ) ;
}
2015-05-18 13:34:40 +00:00
if ( networkOptions . network != null ) {
return callback ( ) ;
}
2015-07-27 12:08:55 +00:00
return form . run ( [
{
message : 'Network Type' ,
name : 'network' ,
type : 'list' ,
choices : [ 'ethernet' , 'wifi' ]
} , {
message : 'Wifi Ssid' ,
name : 'wifiSsid' ,
type : 'input' ,
when : {
network : 'wifi'
}
} , {
message : 'Wifi Key' ,
name : 'wifiKey' ,
type : 'input' ,
when : {
network : 'wifi'
}
2015-04-20 17:03:19 +00:00
}
2015-07-27 12:08:55 +00:00
] ) . then ( function ( parameters ) {
return _ . extend ( networkOptions , parameters ) ;
} ) . nodeify ( callback ) ;
2015-05-18 13:34:40 +00:00
} , function ( callback ) {
console . info ( "Checking application: " + options . application ) ;
2015-07-22 22:06:53 +00:00
return resin . models . application . get ( options . application ) . nodeify ( callback ) ;
2015-05-18 13:34:40 +00:00
} , function ( application , callback ) {
2015-06-04 12:55:32 +00:00
return async . parallel ( {
manifest : function ( callback ) {
console . info ( 'Getting device manifest for the application' ) ;
2015-07-22 22:06:53 +00:00
return resin . models . device . getManifestBySlug ( application . device _type ) . nodeify ( callback ) ;
2015-06-04 12:55:32 +00:00
} ,
config : function ( callback ) {
console . info ( 'Fetching application configuration' ) ;
2015-07-22 22:06:53 +00:00
return deviceConfig . get ( options . application , networkOptions ) . nodeify ( callback ) ;
2015-06-04 12:55:32 +00:00
}
} , callback ) ;
} , function ( results , callback ) {
2015-05-07 15:40:12 +00:00
params . manifest = results . manifest ;
2015-06-04 12:55:32 +00:00
console . info ( 'Associating the device' ) ;
return registerDevice . register ( pine , results . config , function ( error , device ) {
if ( error != null ) {
return callback ( error ) ;
}
results . config . deviceId = device . id ;
results . config . uuid = device . uuid ;
2015-07-14 12:22:44 +00:00
results . config . registered _at = Math . floor ( Date . now ( ) / 1000 ) ;
2015-06-04 12:55:32 +00:00
params . uuid = results . config . uuid ;
return callback ( null , results ) ;
} ) ;
} , function ( results , callback ) {
2015-05-18 13:34:40 +00:00
var bar , spinner ;
2015-08-18 10:55:04 +00:00
console . info ( 'Initializing device operating system image' ) ;
2015-08-18 12:43:52 +00:00
console . info ( 'This may take a few minutes' ) ;
2015-06-04 12:55:32 +00:00
if ( process . env . DEBUG ) {
console . log ( results . config ) ;
}
2015-07-29 13:34:31 +00:00
bar = new visuals . Progress ( 'Downloading Device OS' ) ;
spinner = new visuals . Spinner ( 'Downloading Device OS (size unknown)' ) ;
2015-05-07 15:40:12 +00:00
return manager . configure ( params . manifest , results . config , function ( error , imagePath , removeCallback ) {
2015-06-04 12:55:32 +00:00
spinner . stop ( ) ;
return callback ( error , imagePath , removeCallback ) ;
} , function ( state ) {
if ( state != null ) {
return bar . update ( state ) ;
} else {
return spinner . start ( ) ;
2015-04-20 17:03:19 +00:00
}
2015-05-18 13:34:40 +00:00
} ) ;
} , function ( configuredImagePath , removeCallback , callback ) {
var bar ;
2015-05-07 15:40:12 +00:00
console . info ( 'The base image was cached to improve initialization time of similar devices' ) ;
2015-05-18 13:34:40 +00:00
console . info ( 'Attempting to write operating system image to drive' ) ;
2015-07-29 13:34:31 +00:00
bar = new visuals . Progress ( 'Writing Device OS' ) ;
2015-05-18 13:34:40 +00:00
return image . write ( {
device : params . device ,
image : configuredImagePath ,
progress : _ . bind ( bar . update , bar )
} , function ( error ) {
if ( error != null ) {
return callback ( error ) ;
}
return callback ( null , configuredImagePath , removeCallback ) ;
2015-04-20 17:03:19 +00:00
} ) ;
2015-05-18 13:34:40 +00:00
} , function ( temporalImagePath , removeCallback , callback ) {
console . info ( 'Image written successfully' ) ;
return removeCallback ( callback ) ;
2015-06-04 12:55:32 +00:00
} , function ( callback ) {
2015-07-22 22:06:53 +00:00
return resin . models . device . get ( params . uuid ) . nodeify ( callback ) ;
2015-06-04 12:55:32 +00:00
} , function ( device , callback ) {
console . info ( "Device created: " + device . name ) ;
2015-05-07 15:40:12 +00:00
return callback ( null , params . uuid ) ;
2015-02-26 15:47:56 +00:00
}
] , done ) ;
}
} ;
} ) . call ( this ) ;