Page Menu
Home
c4science
Search
Configure Global Search
Log In
Files
F91333872
AdbDevice.js
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Sun, Nov 10, 02:28
Size
8 KB
Mime Type
text/x-c++
Expires
Tue, Nov 12, 02:28 (2 d)
Engine
blob
Format
Raw Data
Handle
22221720
Attached To
R12545 Sesame - Import/Export Tool
AdbDevice.js
View Options
const Device = require("./Device")
const fs = require("fs-extra");
const toast = require("../helper/toasts");
const files = require("../helper/files");
const path = require("path");
const {Adb} = require("@devicefarmer/adbkit");
const Bluebird = require('bluebird')
let client = Adb.createClient()
class AdbDevice extends Device {
constructor(brand, model, id) {
super()
this.brand = brand
this.model = model
this.id = id
this.name = `${brand} ${model} - ${id}`
this.deviceClient = client.getDevice(id)
}
/**
* Download all logs found inside the sub-folder /ExperimentLogs. The files are downloaded recursively.
* @param destinationFolder where the files should be saved to
* @returns {Promise<boolean>} true: download complete, false otherwise
*/
async downloadLogs(destinationFolder) {
try {
// get all files to download
const fileList = await this.getFilesRecursively('', AdbDevice.PATH + '/ExperimentLogs')
// download one file after the other
for (const file of fileList) {
const transfer = await this.deviceClient.pull(AdbDevice.PATH + '/ExperimentLogs' + file)
await new Bluebird(function (resolve, reject) {
const filename = destinationFolder + file
// make sure the target folder exists
if (!fs.existsSync(path.dirname(filename))) {
fs.mkdirSync(path.dirname(filename), {recursive: true})
}
transfer.on('end', () => {
console.log(`download complete: ${file}`)
resolve();
})
transfer.on('error', () => {
console.error(`download error on file: ${file}`)
reject();
})
transfer.pipe(fs.createWriteStream(filename))
})
}
} catch (e) {
console.error(e.message)
return false
}
return true
}
/**
* Upload a list of files. Each entry in the array must contain full source and target name of the file.
*
* @param fileList array of objects having the attributes "source" and "target"
* @returns {Promise<boolean>} true: all uploads complete, false otherwise
*/
async upload(fileList) {
try {
for (const file of fileList) {
// start the upload of one file
const transfer = await this.deviceClient.push(file.source, file.target)
// wait for a result to arrive. will throw an exception if something goes wrong
await new Bluebird(function (resolve, reject) {
transfer.on('end', () => {
console.log(`upload completed: ${file.source}`)
resolve()
})
transfer.on('error', () => {
console.error(`upload error on file: ${file.source}`)
reject()
})
})
}
} catch (e) {
console.error(e.message)
return false
}
return true
}
/**
* Upload a file and rename it "config.json". The file will be placed where the game is looking for the
* configuration.
* @param file configuration file to rename and upload
* @returns {Promise<boolean>} true: upload complete, false otherwise
*/
async uploadConfig(file) {
return await this.upload([{source: file, target: AdbDevice.PATH + '/config.json'}])
}
/**
* Prepares a list of files and uploads them after preparing. Preparing means: converting the list into list of
* objects with properties "source" and "target". The files will be uploaded into the given sub-folder.
* @param filePaths list of files to upload with full (absolute) file names
* @param subFolder sub-folder on the target device
* @returns {Promise<boolean>} true: all files uploaded, false otherwise
*/
async prepareAndUpload(filePaths, subFolder) {
let fileList = files.prepare(filePaths, AdbDevice.PATH + '/' + subFolder + '/')
return await this.upload(fileList)
}
/**
* Deletes a list of files with names that are relative to "rootFolder".
* @param fileList list of files to delete, with relative file names
* @param rootFolder root folder where all files to be deleted are contained
* @returns {Promise<boolean>} true: all files deleted successfully, false otherwise
*/
async remove(fileList, rootFolder) {
try {
for (const file of fileList) {
// delete a file
const command = await this.deviceClient.shell(`rm -rf "${rootFolder}${file}"`)
// wait for the result of this command
await new Bluebird(function (resolve, reject) {
command.on('end', () => {
console.log(`file deleted: ${rootFolder + file}`)
resolve()
})
command.on('error', () => {
console.error(`error deleting file: ${rootFolder + file}`)
reject()
})
})
}
} catch (e) {
console.error(e.message)
return false
}
return true
}
/**
* Get a list of all files inside "rootFolder" recursively. Can include folders if flag is set. The resulting list
* will contain file names relative to "rootFolder".
* @param subFolder <b>leave empty</b>. used on recursive calls.
* @param rootFolder root folder where to start looking for files
* @param includeFolders whether or not the resulting list should include folders
* @returns {Promise<*[]>} list of files
*/
async getFilesRecursively(subFolder, rootFolder, includeFolders) {
let results = []
const fileList = await this.deviceClient.readdir(rootFolder)
// for each entry in the directory
for (const file of fileList) {
if (!file.isFile()) {
// for folders: read the content of this folder and add all files to the result list
results = results.concat(await this.getFilesRecursively(subFolder + "/" + file.name, rootFolder + "/" + file.name))
}
if (file.isFile() || includeFolders) {
// for files: add relative path of this file to the result list. add folders as well if the flag is set
results.push(subFolder + "/" + file)
}
}
return results
}
/**
* Get the absolute path of the game files and concatenate it if a given list of sub-folders (if present).
* @param subFolders string to concatenate to the path. should not have any "/" at start and end
* @returns {string} path of game files, concatenated with "subFolder"
*/
getPath(subFolders) {
let result = AdbDevice.PATH
if (subFolders) {
for (const folder of subFolders) {
result += '/' + folder
}
}
return result
}
/**
* The name of this device.
* @returns {string} the name
*/
toString() {
return this.name
}
/**
* Get a list of connected ADB devices. For this to work, a standalone ADB server must be running on the host
* device.
* @returns {Promise<*[]>} list of devices
*/
static async getDevices() {
let devices = []
if (client) {
try {
let adbDevices = await client.listDevices()
// read all devices that answer to ADB
const deviceList = await Bluebird.map(adbDevices, async (device) => {
const properties = await client.getDevice(device.id).getProperties()
return new AdbDevice(properties['ro.product.manufacturer'], properties['ro.product.model'], device.id)
})
// store devices in variable for later use
devices = devices.concat(deviceList)
} catch (err) {
console.error(err.message)
toast.create("Erreur de detection d'appareil adb. Acceptez la connexion sur l'appareil.", 'text-bg-danger', 10)
}
}
return devices
}
// ---------
// constants
// ---------
/**
* The root folder where the game files are stored.
*/
static get PATH() {
return '/sdcard/Android/data/com.HEIAFR.ImmersiveSeriousGameFactory/files'
}
/**
* The type of this device.
*/
static get TYPE() {
return 'adb'
}
}
module.exports = AdbDevice;
Event Timeline
Log In to Comment