particle-api-js
Version:
Particle API Client
1,053 lines (977 loc) • 139 kB
JavaScript
const Defaults = require('./Defaults');
const EventStream = require('./EventStream');
const Agent = require('./Agent');
const Client = require('./Client');
/**
* Particle Cloud API wrapper.
*
* See <https://docs.particle.io/reference/javascript/> for examples
* of using the `Particle` class.
*
* Most Particle methods take a single unnamed argument object documented as
* `options` with key/value pairs for each option.
*
* @typedef {import('./Agent').RequestResponse} RequestResponse
* @typedef {import('./Agent').RequestError} RequestError
*/
// These typedef avoid importing the type on every @return statement
class Particle {
/**
* Contructor for the Cloud API wrapper.
*
* Create a new Particle object and call methods below on it.
*
* @param {Object} options Options for this API call Options to be used for all requests (see [Defaults](../src/Defaults.js))
* @param {string} [options.baseUrl]
* @param {string} [options.clientSecret]
* @param {string} [options.clientId]
* @param {number} [options.tokenDuration]
* @param {string} [options.auth] The access token. If not specified here, will have to be added to every request
*/
constructor(options = {}){
if (options.auth) {
this.setDefaultAuth(options.auth);
}
// todo - this seems a bit dangerous - would be better to put all options/context in a contained object
Object.assign(this, Defaults, options);
this.context = {};
this.agent = new Agent(this.baseUrl);
}
_isValidContext(name, context){
return (name === 'tool' || name === 'project') && context !== undefined;
}
/**
* @typedef {Object} ToolContext
* @property {string} name
* @property {string | number} [version]
* @property {Omit<ToolContext, 'components'>[]} [components]
*/
/**
* @typedef {Record<string, string | number>} ProjectContext
* @property {string} name
*/
/**
* Allows setting a tool or project context which will be sent as headers with every request.
* Tool- x-particle-tool
* Project- x-particle-project
* @param {'tool' | 'project'} name
* @param {ToolContext | ProjectContext | undefined} context
*/
setContext(name, context){
if (context !== undefined){
if (this._isValidContext(name, context)){
this.context[name] = context;
} else {
throw Error('unknown context name or undefined context: ' + name);
}
}
}
/**
* Builds the final context from the context parameter and the context items in the api.
* @param {Object} context The invocation context, this takes precedence over the local context.
* @returns {Object} The context to use.
* @private
*/
_buildContext(context){
return Object.assign(this.context, context);
}
/**
* Login to Particle Cloud using an existing Particle acccount.
* @param {Object} options Options for this API call
* @param {String} options.username Username for the Particle account
* @param {String} options.password Password for the Particle account
* @param {Number} options.tokenDuration How long the access token should last in seconds
* @param {Object} [options.headers] Key/Value pairs like `{ 'X-FOO': 'foo', X-BAR: 'bar' }` to send as headers.
* @param {Number} [options.context] Request context
* @returns {Promise} A promise
*/
// @ts-ignore
login({ username, password, tokenDuration = this.tokenDuration, headers, context }){
return this.request({
uri: '/oauth/token',
method: 'post',
headers,
form: {
username,
password,
grant_type: 'password',
// @ts-ignore
client_id: this.clientId,
// @ts-ignore
client_secret: this.clientSecret,
expires_in: tokenDuration
},
context
});
}
/**
* If login failed with an 'mfa_required' error, this must be called with a valid OTP code to login
* @param {Object} options Options for this API call
* @param {String} options.mfaToken Given as 'mfa_token' in the error body of `.login()`.
* @param {String} options.otp Current one-time-password generated from the authentication application
* @param {Object} [options.headers] Key/Value pairs like `{ 'X-FOO': 'foo', X-BAR: 'bar' }` to send as headers.
* @param {Number} [options.context] Request context
* @returns {Promise} A promise
*/
sendOtp({ mfaToken, otp, headers, context }){
return this.request({
uri: '/oauth/token',
method: 'post',
headers,
form: {
grant_type: 'urn:custom:mfa-otp',
mfa_token: mfaToken,
otp,
// @ts-ignore
client_id: this.clientId,
// @ts-ignore
client_secret: this.clientSecret
},
context
});
}
/**
* Enable MFA on the currently logged in user
* @param {Object} options Options for this API call
* @param {string} [options.auth] The access token. Can be ignored if provided in constructor
* @param {Object} [options.headers] Key/Value pairs like `{ 'X-FOO': 'foo', X-BAR: 'bar' }` to send as headers.
* @param {Object} [options.context] Request context
* @returns {Promise} A promise
*/
enableMfa({ auth, headers, context }){
return this.get({ uri: '/v1/user/mfa-enable', auth, headers, context });
}
/**
* Confirm MFA for the user. This must be called with current TOTP code, determined from the results of enableMfa(). You will be prompted to enter an OTP code every time you login after enrollment is confirmed.
* @param {Object} options Options for this API call
* @param {string} [options.auth] The access token. Can be ignored if provided in constructor
* @param {Object} options.mfaToken Token given from previous step to
* @param {Object} options.otp Current one-time-password generated from the authentication app
* @param {Boolean} options.invalidateTokens Should all tokens be invalidated
* @param {Object} [options.headers] Key/Value pairs like `{ 'X-FOO': 'foo', X-BAR: 'bar' }` to send as headers.
* @param {Object} [options.context] Request context
* @returns {Promise} A promise
*/
confirmMfa({ mfaToken, otp, invalidateTokens = false, auth, headers, context }){
let data = { mfa_token: mfaToken, otp };
if (invalidateTokens) {
data.invalidate_tokens = true;
}
return this.post({
uri: '/v1/user/mfa-enable',
auth,
headers,
data,
context
});
}
/**
* Disable MFA for the user.
* @param {Object} options Options for this API call
* @param {string} [options.auth] The access token. Can be ignored if provided in constructor
* @param {Object} options.currentPassword User's current password
* @param {Object} [options.headers] Key/Value pairs like `{ 'X-FOO': 'foo', X-BAR: 'bar' }` to send as headers.
* @param {Object} [options.context] Request context
* @returns {Promise} A promise
*/
disableMfa({ currentPassword, auth, headers, context }){
return this.put({
uri: '/v1/user/mfa-disable',
auth,
headers,
data: { current_password: currentPassword },
context
});
}
/**
* Create Customer for Product.
* @param {Object} options Options for this API call
* @param {String} options.email Username for the Particle account
* @param {String} options.password Password for the Particle account
* @param {String} options.product Create the customer in this product ID or slug
* @param {Object} [options.headers] Key/Value pairs like `{ 'X-FOO': 'foo', X-BAR: 'bar' }` to send as headers.
* @param {Object} [options.context] Request context
* @returns {Promise} A promise
*/
createCustomer({ email, password, product, headers, context }){
return this.request({
uri: `/v1/products/${product}/customers`,
method: 'post',
headers,
form: {
email,
password,
grant_type: 'client_credentials',
// @ts-ignore
client_id: this.clientId,
// @ts-ignore
client_secret: this.clientSecret
},
context
});
}
/**
* Login to Particle Cloud using an OAuth client.
* @param {Object} options Options for this API call
* @param {Object} [options.headers] Key/Value pairs like `{ 'X-FOO': 'foo', X-BAR: 'bar' }` to send as headers.
* @param {Object} [options.context] Request context
* @returns {Promise} A promise
*/
loginAsClientOwner({ headers, context }){
return this.request({
uri: '/oauth/token',
method: 'post',
headers,
form: {
grant_type: 'client_credentials',
// @ts-ignore
client_id: this.clientId,
// @ts-ignore
client_secret: this.clientSecret
},
context
});
}
/**
* Create a user account for the Particle Cloud
* @param {Object} options Options for this API call
* @param {String} options.username Email of the new user
* @param {String} options.password Password
* @param {String} options.accountInfo Object that contains account information fields such as user real name, company name, business account flag etc
* @param {Object} [options.utm] Object that contains info about the campaign that lead to this user creation
* @param {Object} [options.headers] Key/Value pairs like `{ 'X-FOO': 'foo', X-BAR: 'bar' }` to send as headers.
* @param {Object} [options.context] Request context
* @returns {Promise} A promise
*/
createUser({ username, password, accountInfo, utm, headers, context }){
return this.post({
uri: '/v1/users',
headers,
data: {
username,
password,
account_info: accountInfo,
utm
},
context
});
}
/**
* Verify new user account via verification email
* @param {Object} options Options for this API call
* @param {String} options.token The string token sent in the verification email
* @param {Object} [options.headers] Key/Value pairs like `{ 'X-FOO': 'foo', X-BAR: 'bar' }` to send as headers.
* @param {Object} [options.context] Request context
* @returns {Promise} A promise
*/
verifyUser({ token, headers, context }){
return this.post({
uri: '/v1/user/verify',
headers,
data: { token },
context
});
}
/**
* Send reset password email for a Particle Cloud user account
* @param {Object} options Options for this API call
* @param {String} options.username Email of the user
* @param {Object} [options.headers] Key/Value pairs like `{ 'X-FOO': 'foo', X-BAR: 'bar' }` to send as headers.
* @param {Object} [options.context] Request context
* @returns {Promise} A promise
*/
resetPassword({ username, headers, context }){
return this.post({
uri: '/v1/user/password-reset',
headers,
data: { username },
context
});
}
/**
* Revoke an access token
* @param {Object} options Options for this API call
* @param {String} options.token Access token you wish to revoke
* @param {Object} [options.headers] Key/Value pairs like `{ 'X-FOO': 'foo', X-BAR: 'bar' }` to send as headers.
* @param {Object} [options.context] Request context
* @returns {Promise} A promise
*/
deleteAccessToken({ token, headers, context }){
return this.delete({
uri: `/v1/access_tokens/${token}`,
headers,
context
});
}
/**
* Revoke the current session access token
* @param {Object} options Options for this API call
* @param {string} [options.auth] The access token. Can be ignored if provided in constructor
* @param {Object} [options.headers] Key/Value pairs like `{ 'X-FOO': 'foo', X-BAR: 'bar' }` to send as headers.
* @param {Object} [options.context] Request context
* @returns {Promise} A promise
*/
deleteCurrentAccessToken({ auth, headers, context }){
return this.delete({
uri: '/v1/access_tokens/current',
auth,
headers,
context
});
}
/**
* Revoke all active access tokens
* @param {Object} options Options for this API call
* @param {string} [options.auth] The access token. Can be ignored if provided in constructor
* @param {Object} [options.headers] Key/Value pairs like `{ 'X-FOO': 'foo', X-BAR: 'bar' }` to send as headers.
* @param {Object} [options.context] Request context
* @returns {Promise} A promise
*/
deleteActiveAccessTokens({ auth, headers, context }){
return this.delete({
uri: '/v1/access_tokens',
auth,
headers,
context
});
}
/**
* Delete the current user
* @param {Object} options Options for this API call
* @param {string} [options.auth] The access token. Can be ignored if provided in constructor
* @param {String} options.password Password
* @param {Object} [options.headers] Key/Value pairs like `{ 'X-FOO': 'foo', X-BAR: 'bar' }` to send as headers.
* @param {Object} [options.context] Request context
* @returns {Promise} A promise
*/
deleteUser({ auth, password, headers, context }){
return this.delete({
uri: '/v1/user',
data: { password },
auth,
headers,
context
});
}
/**
* Retrieves the information that is used to identify the current login for tracking.
* @param {Object} [options] Options for this API call
* @param {string} [options.auth] The access token. Can be ignored if provided in constructor
* @param {Boolean} [options.full] When true, retrieve all information for registering a user with the tracking API. When false,
* retrieve only the unique tracking ID for the current login.
* @param {Object} [options.headers] Key/Value pairs like `{ 'X-FOO': 'foo', X-BAR: 'bar' }` to send as headers.
* @param {Object} [options.context] Request context
* @returns {Promise<Object>} Resolve the tracking identify of the current login
*/
trackingIdentity({ full = false, auth, headers, context } = {}){
return this.get({
uri: '/v1/user/identify',
auth,
headers,
query: (full ? undefined : { tracking: 1 }),
context
});
}
/**
* List devices claimed to the account or product
* @param {Object} options Options for this API call
* @param {String} [options.deviceId] (Product only) Filter results to devices with this ID (partial matching)
* @param {String} [options.deviceName] (Product only) Filter results to devices with this name (partial matching)
* @param {Array.<string>} [options.groups] (Product only) A list of full group names to filter results to devices belonging to these groups only.
* @param {String} [options.sortAttr] (Product only) The attribute by which to sort results. See API docs for options.
* @param {String} [options.sortDir] (Product only) The direction of sorting. See API docs for options.
* @param {Number} [options.page] (Product only) Current page of results
* @param {Number} [options.perPage] (Product only) Records per page
* @param {String} [options.product] List devices in this product ID or slug
* @param {string} [options.auth] The access token. Can be ignored if provided in constructor
* @param {Object} [options.headers] Key/Value pairs like `{ 'X-FOO': 'foo', X-BAR: 'bar' }` to send as headers.
* @param {Object} [options.context] Request context
* @returns {Promise} A promise
*/
listDevices({ deviceId, deviceName, groups, sortAttr, sortDir, page, perPage, product, auth, headers, context }){
let uri, query;
if (product){
uri = `/v1/products/${product}/devices`;
query = {
deviceId,
deviceName,
groups: Array.isArray(groups) ? groups.join(',') : undefined,
sortAttr,
sortDir,
page,
per_page: perPage
};
} else {
uri = '/v1/devices';
}
return this.get({ uri, auth, headers, query, context });
}
/**
* Get detailed informationa about a device
* @param {Object} options Options for this API call
* @param {String} options.deviceId Device ID or Name
* @param {String} [options.product] Device in this product ID or slug
* @param {string} [options.auth] The access token. Can be ignored if provided in constructor
* @param {Object} [options.headers] Key/Value pairs like `{ 'X-FOO': 'foo', X-BAR: 'bar' }` to send as headers.
* @param {Object} [options.context] Request context
* @returns {Promise} A promise
*/
getDevice({ deviceId, product, auth, headers, context }){
const uri = this.deviceUri({ deviceId, product });
return this.get({ uri, auth, headers, context });
}
/**
* Claim a device to the account. The device must be online and unclaimed.
* @param {Object} options Options for this API call
* @param {String} options.deviceId Device ID
* @param {string} [options.auth] The access token. Can be ignored if provided in constructor
* @param {boolean} options.requestTransfer True to request the device be transfered from another user
* @param {Object} [options.headers] Key/Value pairs like `{ 'X-FOO': 'foo', X-BAR: 'bar' }` to send as headers.
* @param {Object} [options.context] Request context
* @returns {Promise} A promise
*/
claimDevice({ deviceId, requestTransfer, auth, headers, context }){
return this.post({
uri: '/v1/devices',
auth,
headers,
data: {
id: deviceId,
request_transfer: !!requestTransfer
},
context
});
}
/**
* Add a device to a product or move device out of quarantine.
* @param {Object} options Options for this API call
* @param {String} options.deviceId Device ID
* @param {Object} options.file A file that contains a single-column list of device IDs, device serial numbers, device IMEIs, or devie ICCIDs.
* Node: Either a path or Buffer. Browser: a File or Blob.
* @param {String} options.product Add to this product ID or slug
* @param {string} [options.auth] The access token. Can be ignored if provided in constructor
* @param {Object} [options.headers] Key/Value pairs like `{ 'X-FOO': 'foo', X-BAR: 'bar' }` to send as headers.
* @param {Object} [options.context] Request context
* @returns {Promise} A promise
*/
addDeviceToProduct({ deviceId, product, file, auth, headers, context }){
let files, data;
if (file){
files = { file };
} else if (deviceId){
data = { id: deviceId };
}
return this.request({
uri: `/v1/products/${product}/devices`,
method: 'post',
headers,
data,
files,
auth,
context
});
}
/**
* Unclaim / Remove a device from your account or product, or deny quarantine
* @param {Object} options Options for this API call
* @param {String} options.deviceId Device ID or Name
* @param {Boolean} [options.deny] (Product only) Deny this quarantined device, instead of removing an already approved device
* @param {String} options.product Remove from this product ID or slug
* @param {string} [options.auth] The access token. Can be ignored if provided in constructor
* @param {Object} [options.headers] Key/Value pairs like `{ 'X-FOO': 'foo', X-BAR: 'bar' }` to send as headers.
* @param {Object} [options.context] Request context
* @returns {Promise} A promise
*/
removeDevice({ deviceId, deny, product, auth, headers, context }){
const uri = this.deviceUri({ deviceId, product });
const data = product ? { deny } : undefined;
return this.delete({ uri, data, auth, headers, context });
}
/**
* Unclaim a product device its the owner, but keep it in the product
* @param {Object} options Options for this API call
* @param {String} options.deviceId Device ID or Name
* @param {String} options.product Remove from this product ID or slug
* @param {string} [options.auth] The access token. Can be ignored if provided in constructor
* @param {Object} [options.headers] Key/Value pairs like `{ 'X-FOO': 'foo', X-BAR: 'bar' }` to send as headers.
* @param {Object} [options.context] Request context
* @returns {Promise} A promise
*/
removeDeviceOwner({ deviceId, product, auth, headers, context }){
const uri = `/v1/products/${product}/devices/${deviceId}/owner`;
return this.delete({ uri, auth, headers, context });
}
/**
* Rename a device
* @param {Object} options Options for this API call
* @param {String} options.deviceId Device ID or Name
* @param {String} options.name Desired Name
* @param {String} [options.product] Rename device in this product ID or slug
* @param {string} [options.auth] The access token. Can be ignored if provided in constructor
* @param {Object} [options.headers] Key/Value pairs like `{ 'X-FOO': 'foo', X-BAR: 'bar' }` to send as headers.
* @param {Object} [options.context] Request context
* @returns {Promise} A promise
*/
renameDevice({ deviceId, name, product, auth, headers, context }){
return this.updateDevice({ deviceId, name, product, auth, headers, context });
}
/**
* Instruct the device to turn on/off the LED in a rainbow pattern
* @param {Object} options Options for this API call
* @param {String} options.deviceId Device ID or Name
* @param {Boolean} options.signal Signal on or off
* @param {String} [options.product] Device in this product ID or slug
* @param {string} [options.auth] The access token. Can be ignored if provided in constructor
* @param {Object} [options.headers] Key/Value pairs like `{ 'X-FOO': 'foo', X-BAR: 'bar' }` to send as headers.
* @param {Object} [options.context] Request context
* @returns {Promise} A promise
*/
signalDevice({ deviceId, signal, product, auth, headers, context }){
return this.updateDevice({ deviceId, signal, product, auth, headers, context });
}
/**
* Store some notes about device
* @param {Object} options Options for this API call
* @param {String} options.deviceId Device ID or Name
* @param {String} options.notes Your notes about this device
* @param {String} [options.product] Device in this product ID or slug
* @param {string} [options.auth] The access token. Can be ignored if provided in constructor
* @param {Object} [options.headers] Key/Value pairs like `{ 'X-FOO': 'foo', X-BAR: 'bar' }` to send as headers.
* @param {Object} [options.context] Request context
* @returns {Promise} A promise
*/
setDeviceNotes({ deviceId, notes, product, auth, headers, context }){
return this.updateDevice({ deviceId, notes, product, auth, headers, context });
}
/**
* Mark device as being used in development of a product so it opts out of automatic firmware updates
* @param {Object} options Options for this API call
* @param {String} options.deviceId Device ID or Name
* @param {Boolean} options.development Set to true to mark as development, false to return to product fleet
* @param {String} options.product Device in this product ID or slug
* @param {string} [options.auth] The access token. Can be ignored if provided in constructor
* @param {Object} [options.headers] Key/Value pairs like `{ 'X-FOO': 'foo', X-BAR: 'bar' }` to send as headers.
* @param {Object} [options.context] Request context
* @returns {Promise} A promise
*/
markAsDevelopmentDevice({ deviceId, development = true, product, auth, headers, context }){
return this.updateDevice({ deviceId, development, product, auth, headers, context });
}
/**
* Mark device as being used in development of a product, so it opts out of automatic firmware updates
* @param {Object} options Options for this API call
* @param {String} options.deviceId Device ID or Name
* @param {Number} options.desiredFirmwareVersion Lock the product device to run this firmware version.
* @param {Boolean} [options.flash] Immediately flash firmware indicated by desiredFirmwareVersion
* @param {String} options.product Device in this product ID or slug
* @param {string} [options.auth] The access token. Can be ignored if provided in constructor
* @param {Object} [options.headers] Key/Value pairs like `{ 'X-FOO': 'foo', X-BAR: 'bar' }` to send as headers.
* @param {Object} [options.context] Request context
* @returns {Promise} A promise
*/
lockDeviceProductFirmware({ deviceId, desiredFirmwareVersion, flash, product, auth, headers, context }){
return this.updateDevice({ deviceId, desiredFirmwareVersion, flash, product, auth, headers, context });
}
/**
* Mark device as receiving automatic firmware updates
* @param {Object} options Options for this API call
* @param {String} options.deviceId Device ID or Name
* @param {String} options.product Device in this product ID or slug
* @param {string} [options.auth] The access token. Can be ignored if provided in constructor
* @param {Object} [options.headers] Key/Value pairs like `{ 'X-FOO': 'foo', X-BAR: 'bar' }` to send as headers.
* @param {Object} [options.context] Request context
* @returns {Promise} A promise
*/
unlockDeviceProductFirmware({ deviceId, product, auth, headers, context }){
return this.updateDevice({ deviceId, desiredFirmwareVersion: null, product, auth, headers, context });
}
/**
* Update multiple device attributes at the same time
* @param {Object} options Options for this API call
* @param {String} options.deviceId Device ID or Name
* @param {String} [options.name] Desired Name
* @param {Boolean} [options.signal] Signal device on or off
* @param {String} [options.notes] Your notes about this device
* @param {Boolean} [options.development] (Product only) Set to true to mark as development, false to return to product fleet
* @param {Number | null} [options.desiredFirmwareVersion] (Product only) Lock the product device to run this firmware version.
* Pass `null` to unlock firmware and go back to released firmware.
* @param {Boolean} [options.flash] (Product only) Immediately flash firmware indicated by desiredFirmwareVersion
* @param {String} [options.product] Device in this product ID or slug
* @param {string} [options.auth] The access token. Can be ignored if provided in constructor
* @param {Object} [options.headers] Key/Value pairs like `{ 'X-FOO': 'foo', X-BAR: 'bar' }` to send as headers.
* @param {Object} [options.context] Request context
* @returns {Promise} A promise
*/
updateDevice({ deviceId, name, signal, notes, development, desiredFirmwareVersion, flash, product, auth, headers, context }){
let signalValue;
if (signal !== undefined){
signalValue = signal ? '1' : '0';
}
const uri = this.deviceUri({ deviceId, product });
const data = product ?
{ name, signal: signalValue, notes, development, desired_firmware_version: desiredFirmwareVersion, flash } :
{ name, signal: signalValue, notes };
return this.put({ uri, auth, headers, data, context });
}
/**
* Disable device protection.
*
* @param {Object} options Options for this API call.
* @param {String} options.deviceId Device ID or name.
* @param {String} options.action Request action: `prepare` or `confirm`.
* @param {String} [options.org] Organziation ID or slug.
* @param {String} [options.product] Product ID or slug.
* @param {String} [options.serverNonce] Base64-encoded server nonce. Mandatory if `action` is `confirm`,
* @param {String} [options.deviceNonce] Base64-encoded device nonce. Mandatory if `action` is `confirm`,
* @param {String} [options.deviceSignature] Base64-encoded device signature. Mandatory if `action` is `confirm`,
* @param {String} [options.devicePublicKeyFingerprint] Base64-encoded fingerprint of the device public key.
* Mandatory if `action` is `confirm`,
* @param {string} [options.auth] The access token. Can be ignored if provided in constructor.
* @param {Object} [options.headers] Key/value pairs to send as headers.
* @param {Object} [options.context] Request context.
* @returns {Promise} A promise
*/
unprotectDevice({ deviceId, org, product, action, serverNonce, deviceNonce, deviceSignature, devicePublicKeyFingerprint, auth, headers, context }) {
const data = { action };
if (deviceNonce !== undefined) {
data.device_nonce = deviceNonce;
}
if (serverNonce !== undefined) {
data.server_nonce = serverNonce;
}
if (deviceSignature !== undefined) {
data.device_signature = deviceSignature;
}
if (devicePublicKeyFingerprint !== undefined) {
data.device_public_key_fingerprint = devicePublicKeyFingerprint;
}
const uri = this.deviceUri({ deviceId, product, org }) + '/unprotect';
return this.put({ uri, data, auth, headers, context });
}
/**
* Provision a new device for products that allow self-provisioning
* @param {Object} options Options for this API call
* @param {String} options.productId Product ID where to create this device
* @param {string} [options.auth] The access token. Can be ignored if provided in constructor
* @param {Object} [options.headers] Key/Value pairs like `{ 'X-FOO': 'foo', X-BAR: 'bar' }` to send as headers.
* @param {Object} [options.context] Request context
* @returns {Promise} A promise
*/
provisionDevice({ productId, auth, headers, context }){
return this.post({
uri: '/v1/devices',
auth,
headers,
data: { product_id: productId },
context
});
}
/**
* Generate a claim code to use in the device claiming process.
* To generate a claim code for a product, the access token MUST belong to a
* customer of the product.
* @param {Object} options Options for this API call
* @param {String} [options.iccid] ICCID of the SIM card used in the Electron
* @param {String} [options.product] Device in this product ID or slug
* @param {string} [options.auth] The access token. Can be ignored if provided in constructor
* @param {Object} [options.headers] Key/Value pairs like `{ 'X-FOO': 'foo', X-BAR: 'bar' }` to send as headers.
* @param {Object} [options.context] Request context
* @returns {Promise} A promise
*/
getClaimCode({ iccid, product, auth, headers, context }){
const uri = product ? `/v1/products/${product}/device_claims` : '/v1/device_claims';
return this.post({ uri, auth, headers, data: { iccid }, context });
}
validatePromoCode({ promoCode, auth, headers, context }){
return this.get({
uri: `/v1/promo_code/${promoCode}`,
auth,
headers,
context
});
}
/**
* Get the value of a device variable
* @param {Object} options Options for this API call
* @param {String} options.deviceId Device ID or Name
* @param {String} options.name Variable name
* @param {String} [options.product] Device in this product ID or slug
* @param {string} [options.auth] The access token. Can be ignored if provided in constructor
* @param {Object} [options.headers] Key/Value pairs like `{ 'X-FOO': 'foo', X-BAR: 'bar' }` to send as headers.
* @param {Object} [options.context] Request context
* @returns {Promise} A promise
*/
getVariable({ deviceId, name, product, auth, headers, context }){
const uri = product ?
`/v1/products/${product}/devices/${deviceId}/${name}` :
`/v1/devices/${deviceId}/${name}`;
return this.get({ uri, auth, headers, context });
}
/**
* Compile and flash application firmware to a device. Pass a pre-compiled binary to flash it directly to the device.
* @param {Object} options Options for this API call
* @param {String} options.deviceId Device ID or Name
* @param {String} options.product Flash device in this product ID or slug
* @param {Object} options.files Object containing files to be compiled and flashed. Keys should be the filenames, including relative path, and the values should be a path or Buffer of the file contents in Node, or a File or Blob in the browser.
* @param {String} [options.targetVersion=latest] System firmware version to compile against
* @param {string} [options.auth] The access token. Can be ignored if provided in constructor
* @param {Object} [options.headers] Key/Value pairs like `{ 'X-FOO': 'foo', X-BAR: 'bar' }` to send as headers.
* @param {Object} [options.context] Request context
* @returns {Promise} A promise
*/
flashDevice({ deviceId, product, files, targetVersion, auth, headers, context }){
const uri = this.deviceUri({ deviceId, product });
const form = {};
if (targetVersion){
form.build_target_version = targetVersion;
} else {
form.latest = 'true';
}
return this.request({ uri, method: 'put', auth, headers, files, form, context });
}
/**
* DEPRECATED: Flash the Tinker application to a device. Instead compile and flash the Tinker source code.
* @param {Object} options Options for this API call
* @param {String} options.deviceId Device ID or Name
* @param {string} [options.auth] The access token. Can be ignored if provided in constructor
* @param {Object} [options.headers] Key/Value pairs like `{ 'X-FOO': 'foo', X-BAR: 'bar' }` to send as headers.
* @param {Object} [options.context] Request context
* @returns {Promise} A promise
*/
flashTinker({ deviceId, auth, headers, context }){
/* eslint-disable no-console */
/* @ts-ignore */
if (console && console.warning){
// @ts-ignore
console.warning('Particle.flashTinker is deprecated');
}
/* eslint-enable no-console */
return this.put({
uri: `/v1/devices/${deviceId}`,
headers,
data: { app: 'tinker' },
auth,
context
});
}
/**
* Compile firmware using the Particle Cloud
* @param {Object} options Options for this API call
* @param {Object} options.files Object containing files to be compiled. Keys should be the filenames, including relative path, and the values should be a path or Buffer of the file contents in Node, or a File or Blob in the browser.
* @param {Number} [options.platformId] Platform id number of the device you are compiling for. Common values are 0=Core, 6=Photon, 10=Electron.
* @param {String} [options.targetVersion=latest] System firmware version to compile against
* @param {string} [options.auth] The access token. Can be ignored if provided in constructor
* @param {Object} [options.headers] Key/Value pairs like `{ 'X-FOO': 'foo', X-BAR: 'bar' }` to send as headers.
* @param {Object} [options.context] Request context
* @returns {Promise} A promise
*/
compileCode({ files, platformId, targetVersion, auth, headers, context }){
const form = { platform_id: platformId };
if (targetVersion){
form.build_target_version = targetVersion;
} else {
form.latest = 'true';
}
return this.request({
uri: '/v1/binaries',
method: 'post',
auth,
headers,
files,
form,
context
});
}
/**
* Download a firmware binary
* @param {Object} options Options for this API call
* @param {String} options.binaryId Binary ID received from a successful compile call
* @param {string} [options.auth] The access token. Can be ignored if provided in constructor
* @param {Object} [options.headers] Key/Value pairs like `{ 'X-FOO': 'foo', X-BAR: 'bar' }` to send as headers.
* @param {Object} [options.context] Request context
* @returns {Promise<RequestResponse, RequestError>} A promise
*/
downloadFirmwareBinary({ binaryId, auth, headers, context }){
return this.request({
uri: `/v1/binaries/${binaryId}`,
method: 'get',
auth,
headers,
context,
isBuffer: true
});
}
/**
* Send a new device public key to the Particle Cloud
* @param {Object} options Options for this API call
* @param {String} options.deviceId Device ID or Name
* @param {String | Buffer} options.key Public key contents
* @param {String} [options.algorithm=rsa] Algorithm used to generate the public key. Valid values are `rsa` or `ecc`.
* @param {string} [options.auth] The access token. Can be ignored if provided in constructor
* @param {Object} [options.headers] Key/Value pairs like `{ 'X-FOO': 'foo', X-BAR: 'bar' }` to send as headers.
* @param {Object} [options.context] Request context
* @returns {Promise} A promise
*/
sendPublicKey({ deviceId, key, algorithm, auth, headers, context }){
return this.post({
uri: `/v1/provisioning/${deviceId}`,
auth,
headers,
data: {
deviceID: deviceId,
publicKey: ( typeof key === 'string' ? key : key.toString() ),
filename: 'particle-api',
order: `manual_${ Date.now() }`,
algorithm: algorithm || 'rsa'
},
context
});
}
/**
* Call a device function
* @param {Object} options Options for this API call
* @param {String} options.deviceId Device ID or Name
* @param {String} options.name Function name
* @param {String} options.argument Function argument
* @param {String} [options.product] Device in this product ID or slug
* @param {string} [options.auth] The access token. Can be ignored if provided in constructor
* @param {Object} [options.headers] Key/Value pairs like `{ 'X-FOO': 'foo', X-BAR: 'bar' }` to send as headers.
* @param {Object} [options.context] Request context
* @returns {Promise} A promise
*/
callFunction({ deviceId, name, argument, product, auth, headers, context }){
const uri = product ?
`/v1/products/${product}/devices/${deviceId}/${name}` :
`/v1/devices/${deviceId}/${name}`;
return this.post({ uri, auth, headers, data: { args: argument }, context });
}
/**
* Get a stream of events
* @param {Object} options Options for this API call
* @param {String} [options.deviceId] Device ID or Name, or `mine` to indicate only your devices.
* @param {String} [options.name] Event Name
* @param {String} [options.org] Organization Slug
* @param {String} [options.product] Events for this product ID or slug
* @param {string} [options.auth] The access token. Can be ignored if provided in constructor
* @returns {Promise} If the promise resolves, the resolution value will be an EventStream object that will
* emit 'event' events.
*/
getEventStream({ deviceId, name, org, product, auth }){
let uri = '/v1/';
if (org){
uri += `orgs/${org}/`;
}
if (product){
uri += `products/${product}/`;
}
if (deviceId){
uri += 'devices/';
if (!(deviceId.toLowerCase() === 'mine')){
uri += `${deviceId}/`;
}
}
uri += 'events';
if (name){
uri += `/${encodeURIComponent(name)}`;
}
auth = this._getActiveAuthToken(auth);
return new EventStream(`${this.baseUrl}${uri}`, auth).connect();
}
/**
* Publish a event to the Particle Cloud
* @param {Object} options Options for this API call
* @param {String} options.name Event name
* @param {String} options.data Event data
* @param {Boolean} options.isPrivate Should the event be publicly available?
* @param {String} [options.product] Event for this product ID or slug
* @param {string} [options.auth] The access token. Can be ignored if provided in constructor
* @param {Object} [options.headers] Key/Value pairs like `{ 'X-FOO': 'foo', X-BAR: 'bar' }` to send as headers.
* @param {Object} [options.context] Request context
* @returns {Promise} A promise
*/
publishEvent({ name, data, isPrivate, product, auth, headers, context }){
const uri = product ? `/v1/products/${product}/events` : '/v1/devices/events';
const postData = { name, data, private: isPrivate };
return this.post({ uri, auth, headers, data: postData, context });
}
/**
* @typedef {Object} Hook
* @property {String} [method=POST] Type of web request triggered by the Webhook (GET, POST, PUT, or DELETE)
* @property {Object} [auth] Auth data like `{ user: 'me', pass: '1234' }` for basic auth or `{ bearer: 'token' }` to send with the Webhook request
* @property {Object} [headers] Additional headers to add to the Webhook like `{ 'X-ONE': '1', X-TWO: '2' }`
* @property {Object} [query] Query params to add to the Webhook request like `{ foo: 'foo', bar: 'bar' }`
* @property {Object} [json] JSON data to send with the Webhook request - sets `Content-Type` to `application/json`
* @property {Object} [form] Form data to send with the Webhook request - sets `Content-Type` to `application/x-www-form-urlencoded`
* @property {String} [body] Custom body to send with the Webhook request
* @property {Object} [responseTemplate] Template to use to customize the Webhook response body
* @property {Object} [responseEvent] The Webhook response event name that your devices can subscribe to
* @property {Object} [errorResponseEvent] The Webhook error response event name that your devices can subscribe to
*/
/**
* Create a webhook
* @param {Object} options Options for this API call
* @param {String} options.event The name of the Particle event that should trigger the Webhook
* @param {String} options.url The web address that will be targeted when the Webhook is triggered
* @param {String} [options.device] Trigger Webhook only for this device ID or Name
* @param {Boolean} [options.rejectUnauthorized] Set to `false` to skip SSL certificate validation of the target URL
* @param {Boolean} [options.noDefaults] Don't include default event data in the webhook request
* @param {Hook} [options.hook] Webhook configuration settings
* @param {String} [options.product] Webhook for this product ID or slug
* @param {string} [options.auth] The access token. Can be ignored if provided in constructor
* @param {Object} [options.headers] Key/Value pairs like `{ 'X-FOO': 'foo', X-BAR: 'bar' }` to send as headers.
* @param {Object} [options.context] Request context
* @returns {Promise} A promise
*/
createWebhook({ event, url, device, rejectUnauthorized, noDefaults, hook, product, auth, headers, context }){
const uri = product ? `/v1/products/${product}/webhooks` : '/v1/webhooks';
const data = { event, url, deviceId: device, rejectUnauthorized, noDefaults };
if (hook){
data.requestType = hook.method;
data.auth = hook.auth;
data.headers = hook.headers;
data.query = hook.query;
data.json = hook.json;
data.form = hook.form;
data.body = hook.body;
data.responseTemplate = hook.responseTemplate;
data.responseTopic = hook.responseEvent;
data.errorResponseTopic = hook.errorResponseEvent;
}
if (!data.requestType){
data.requestType = 'POST';
}
return this.post({ uri, auth, headers, data, context });
}
/**
* Delete a webhook
* @param {Object} options Options for this API call
* @param {String} options.hookId Webhook ID
* @param {String} [options.product] Webhook for this product ID or slug
* @param {string} [options.auth] The access token. Can be ignored if provided in constructor
* @param {Object} [options.headers] Key/Value pairs like `{ 'X-FOO': 'foo', X-BAR: 'bar' }` to send as headers.
* @param {Object} [options.context] Request context
* @returns {Promise} A promise
*/
deleteWebhook({ hookId, product, auth, headers, context }){
const uri = product ? `/v1/products/${product}/webhooks/${hookId}` : `/v1/webhooks/${hookId}`;
return this.delete({ uri, auth, headers, context });
}
/**
* List all webhooks owned by the account or product
* @param {Object} options Options for this API call
* @param {String} [options.product] Webhooks for this product ID or slug
* @param {string} [options.auth] The access token. Can be ignored if provided in constructor
* @param {Object} [options.headers] Key/Value pairs like `{ 'X-FOO': 'foo', X-BAR: 'bar' }` to send as headers.
* @param {Object} [options.context] Request context
* @returns {Promise} A promise
*/
listWebhooks({ product, auth, headers, context }){
const uri = product ? `/v1/products/${product}/webhooks` : '/v1/webhooks';
return this.get({ uri, auth, headers, context });
}
/**
* Create an integration to send events to an external service
*
* See the API docs for details https://docs.particle.io/reference/api/#integrations-webhooks-
*
* @param {Object} options Options for this API call