diff --git a/types/i2c-bus/i2c-bus-tests.ts b/types/i2c-bus/i2c-bus-tests.ts index 599e7c6599..fee8b16f4d 100644 --- a/types/i2c-bus/i2c-bus-tests.ts +++ b/types/i2c-bus/i2c-bus-tests.ts @@ -1,152 +1,81 @@ // Tests for i2c-bus/index.d.ts // Project: https://github.com/fivdi/i2c-bus // Definitions by: Jason Heard +// Kohei Watanabe // Tests taken from documentation samples. -import { I2cBus, open, openSync } from "i2c-bus"; -import * as async from "async"; +import { openPromisified, open, openSync } from 'i2c-bus'; -function toCelsius(rawTemp: number): number { - const halfDegrees = ((rawTemp & 0xff) << 1) + (rawTemp >> 15); +const MCP9808_ADDR = 0x18; +const TEMP_REG = 0x05; - if ((halfDegrees & 0x100) === 0) { - return halfDegrees / 2; // Temp +ve +const toCelsius = (rawData: number) => { + rawData = (rawData >> 8) + ((rawData & 0xff) << 8); + let celsius = (rawData & 0x0fff) / 16; + if (rawData & 0x1000) { + celsius -= 256; } - - return -((~halfDegrees & 0xff) / 2); // Temp -ve -} - + return celsius; +}; /** * Example 1 from the i2c-bus README file. */ function example1(): void { - const i2c1 = openSync(1); - - const DS1621_ADDR = 0x48, - CMD_ACCESS_CONFIG = 0xac, - CMD_READ_TEMP = 0xaa, - CMD_START_CONVERT = 0xee; - - // Enter one shot mode (this is a non volatile setting) - i2c1.writeByteSync(DS1621_ADDR, CMD_ACCESS_CONFIG, 0x01); - - // Wait while non volatile memory busy - while (i2c1.readByteSync(DS1621_ADDR, CMD_ACCESS_CONFIG) & 0x10) { - } - - // Start temperature conversion - i2c1.sendByteSync(DS1621_ADDR, CMD_START_CONVERT); - - // Wait for temperature conversion to complete - while ((i2c1.readByteSync(DS1621_ADDR, CMD_ACCESS_CONFIG) & 0x80) === 0) { - } - - // Display temperature - const rawTemp = i2c1.readWordSync(DS1621_ADDR, CMD_READ_TEMP); - console.log("temp: " + toCelsius(rawTemp)); - - i2c1.closeSync(); + openPromisified(1) + .then(i2c1 => + i2c1 + .readWord(MCP9808_ADDR, TEMP_REG) + .then(rawData => console.log(toCelsius(rawData))) + .then(_ => i2c1.close()), + ) + .catch(console.log); } - /** * Example 2 from the i2c-bus README file. */ function example2(): void { - let i2c1: I2cBus; + const wbuf = Buffer.from([TEMP_REG]); + const rbuf = Buffer.alloc(2); - const DS1621_ADDR = 0x48, - CMD_ACCESS_CONFIG = 0xac, - CMD_READ_TEMP = 0xaa, - CMD_START_CONVERT = 0xee; - - async.series([ - cb => { - i2c1 = open(1, cb); - }, - cb => { - // Enter one shot mode (this is a non volatile setting) - i2c1.writeByte(DS1621_ADDR, CMD_ACCESS_CONFIG, 0x01, cb); - }, - cb => { - // Wait while non volatile memory busy - (function read(): void { - i2c1.readByte(DS1621_ADDR, CMD_ACCESS_CONFIG, (err, config) => { - if (err) return cb(err); - if (config & 0x10) return read(); - cb(undefined); - }); - }()); - }, - cb => { - // Start temperature conversion - i2c1.sendByte(DS1621_ADDR, CMD_START_CONVERT, cb); - }, - cb => { - // Wait for temperature conversion to complete - (function read(): void { - i2c1.readByte(DS1621_ADDR, CMD_ACCESS_CONFIG, (err, config) => { - if (err) return cb(err); - if ((config & 0x80) === 0) return read(); - cb(undefined); - }); - }()); - }, - cb => { - // Display temperature - i2c1.readWord(DS1621_ADDR, CMD_READ_TEMP, (err, rawTemp) => { - if (err) return cb(err); - console.log("temp: " + toCelsius(rawTemp)); - cb(undefined); - }); - }, - cb => { - i2c1.close(cb); - } - ], err => { - if (err) throw err; - }); + openPromisified(1) + .then(i2c1 => + i2c1 + .i2cWrite(MCP9808_ADDR, wbuf.length, wbuf) + .then(_ => i2c1.i2cRead(MCP9808_ADDR, rbuf.length, rbuf)) + .then(data => console.log(toCelsius(data.buffer.readUInt16BE(0)))) + .then(_ => i2c1.close()), + ) + .catch(console.log); } - /** * Example 3 from the i2c-bus README file. */ function example3(): void { - let i2c1: I2cBus; - - const DS1621_ADDR = 0x48, - DS1621_CMD_ACCESS_TH = 0xa1; - - const TSL2561_ADDR = 0x39, - TSL2561_CMD = 0x80, - TSL2561_REG_ID = 0x0a; - - i2c1 = open(1, err => { + const i2c1 = open(1, err => { if (err) throw err; - function readTempHigh(): void { - i2c1.readWord(DS1621_ADDR, DS1621_CMD_ACCESS_TH, (err, tempHigh) => { + i2c1.readWord(MCP9808_ADDR, TEMP_REG, (err, rawData) => { + if (err) throw err; + + console.log(toCelsius(rawData)); + + i2c1.close(err => { if (err) throw err; - console.log("temp: " + tempHigh); - // read another temperature - readTempHigh(); }); - } - - readTempHigh(); - - function readId(): void { - i2c1.readByte(TSL2561_ADDR, TSL2561_CMD | TSL2561_REG_ID, (err, id) => { - if (err) throw err; - console.log("id: " + id); - // read another ID - readId(); - }); - } - - readId(); + }); }); } + +/** + * Example 4 from the i2c-bus README file. + */ +function example4(): void { + const i2c1 = openSync(1); + const rawData = i2c1.readWordSync(MCP9808_ADDR, TEMP_REG); + console.log(toCelsius(rawData)); + i2c1.closeSync(); +} diff --git a/types/i2c-bus/index.d.ts b/types/i2c-bus/index.d.ts index 188210653a..f407f8781c 100644 --- a/types/i2c-bus/index.d.ts +++ b/types/i2c-bus/index.d.ts @@ -1,11 +1,17 @@ -// Type definitions for i2c-bus v1.0.0 +// Type definitions for i2c-bus v5.1.0 // Project: https://github.com/fivdi/i2c-bus // Definitions by: Jason Heard +// Kohei Watanabe // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped -// TypeScript Version: 2.3 +// TypeScript Version: 3.7 /// +type I2CDeviceId = { manufacturer: number; product: number; name: string }; + +type BytesWritten = { bytesWritten: number; buffer: Buffer }; + +type BytesRead = { bytesRead: number; buffer: Buffer }; type CompletionCallback = (error: any) => any; @@ -13,7 +19,12 @@ type BufferCallback = (error: any, bytesReadOrWritten: number, buffer: Buffer) = type ResultCallback = (error: any, result: T) => any; -export interface I2cBusFuncs { +type OpenOptions = { + /** A boolean value specifying whether access to devices on the I2C bus should be allowed even if they are already in use by a kernel driver/module. Corresponds to I2C_SLAVE_FORCE on Linux. The valid values for forceAccess are true and false. Optional, the default value is false. */ + forceAccess: boolean; +}; + +export interface I2CFuncs { i2c: boolean; tenBitAddr: boolean; protocolMangling: boolean; @@ -33,8 +44,7 @@ export interface I2cBusFuncs { smbusWriteI2cBlock: boolean; } -export interface I2cBus { - +export interface I2CBus { /** * Asynchronous close. * @@ -51,21 +61,21 @@ export interface I2cBus { /** * Determine functionality of the bus/adapter asynchronously. * - * @param {ResultCallback} callback + * @param {ResultCallback} callback * Callback that will recieve a frozen I2cFuncs object describing the I2C functionality available. */ - i2cFuncs(callback: ResultCallback): void; + i2cFuncs(callback: ResultCallback): void; /** * Determine functionality of the bus/adapter synchronously. * - * @return {I2cBusFuncs} + * @return {I2CFuncs} * A frozen I2cFuncs object describing the I2C functionality available. */ - i2cFuncsSync(): I2cBusFuncs; + i2cFuncsSync(): I2CFuncs; /** - * Scans the I2C bus asynchronously for devices the same way i2cdetect -y -r would. + * Scans the I2C bus asynchronously for devices. The default address range 0x03 through 0x77 is the same as the default address range used by the i2cdetect command line tool. * * @param {ResultCallback} callback * Callback that will recieve an array of numbers where each number represents the I2C address of a device which was detected. @@ -73,12 +83,68 @@ export interface I2cBus { scan(callback: ResultCallback): void; /** - * Scans the I2C bus synchronously for devices the same way i2cdetect -y -r would. + * Scans the I2C bus asynchronously for devices. The default address range 0x03 through 0x77 is the same as the default address range used by the i2cdetect command line tool. * + * @param {number} address + * An integer specifying the address of the scan. + * @param {ResultCallback} callback + * Callback that will recieve an array of numbers where each number represents the I2C address of a device which was detected. + */ + scan(address: number, callback: ResultCallback): void; + + /** + * Scans the I2C bus asynchronously for devices. The default address range 0x03 through 0x77 is the same as the default address range used by the i2cdetect command line tool. + * + * @param {number} startAddr + * An integer specifying the start address of the scan range. + * @param {number} endAddr + * An integer specifying the end address of the scan range. + * @param {ResultCallback} callback + * Callback that will recieve an array of numbers where each number represents the I2C address of a device which was detected. + */ + scan(startAddr: number, endAddr: number, callback: ResultCallback): void; + + /** + * Scans the I2C bus synchronously for devices. The default address range 0x03 through 0x77 is the same as the default address range used by the i2cdetect command line tool. + * + * @param {number} [address] + * An integer specifying the address of the scan. * @return {number[]} * An array of numbers where each number represents the I2C address of a device which was detected. */ - scanSync(): number[]; + scanSync(address?: number): number[]; + + /** + * Scans the I2C bus synchronously for devices. The default address range 0x03 through 0x77 is the same as the default address range used by the i2cdetect command line tool. + * + * @param {number} [startAddr] + * An integer specifying the start address of the scan range. + * @param {number} [endAddr] + * An integer specifying the end address of the scan range. + * @return {number[]} + * An array of numbers where each number represents the I2C address of a device which was detected. + */ + scanSync(startAddr: number, endAddr: number): number[]; + + /** + * Asynchronous I2C device Id. + * + * @param {number} address + * I2C device address + * @param {ResultCallback} callback + * The callback gets two arguments (err, id). id is an object with the properties manufacturer, product and if known a human readable name for the associated manufacturer. + */ + deviceId(address: number, callback: ResultCallback): void; + + /** + * Synchronous I2C device Id. + * + * @param {number} address + * I2C device address + * @return {I2CDeviceId} + * An object with the properties manufacturer, product and if known a human readable name for the associated manufacturer. + */ + deviceIdSync(address: number): I2CDeviceId; /** * Asynchronous plain I2C read. @@ -376,26 +442,256 @@ export interface I2cBus { */ writeI2cBlockSync(address: number, command: number, length: number, buffer: Buffer): number; + /** + * Return the PromisifiedBus instance for this Bus instance. + * + * @return {PromisifiedBus} + * The PromisifiedBus instance for this Bus instance. + */ + promisifiedBus(): PromisifiedBus; +} + +export interface PromisifiedBus { + /** + * Asynchronous close. + * + * @return {Promise} + * A Promise that will be resolved with no arguments once the underlying resources have been released, or will be rejected if an error occurs while closing. + */ + close(): Promise; + + /** + * Determine functionality of the bus/adapter asynchronously. + * + * @return {Promise} + * A Promise that on success will be resolved with a frozen I2cFuncs object describing the functionality available. The returned Promise will be rejected if an error occurs. See also [I2C functionality](https://www.kernel.org/doc/Documentation/i2c/functionality). + */ + i2cFuncs(): Promise; + + /** + * Scans the I2C bus asynchronously for devices. The default address range 0x03 through 0x77 is the same as the default address range used by the i2cdetect command line tool. + * + * @param {number} [address] + * An integer specifying the address of the scan. + * @return {Promise} + * A Promise that on success will be resolved with an array of numbers where each number represents the I2C address of a device which was detected. The returned Promise will be rejected if an error occurs. + */ + scan(address?: number): Promise; + + /** + * Scans the I2C bus asynchronously for devices. The default address range 0x03 through 0x77 is the same as the default address range used by the i2cdetect command line tool. + * + * @param {number} [startAddr] + * An integer specifying the start address of the scan range. + * @param {number} [endAddr] + * An integer specifying the end address of the scan range. + * @return {Promise} + * A Promise that on success will be resolved with an array of numbers where each number represents the I2C address of a device which was detected. The returned Promise will be rejected if an error occurs. + */ + scan(startAddr: number, endAddr: number): Promise; + + /** + * Asynchronous I2C device Id. + * + * @param {number} address + * I2C device address + * @return {Promise} + * A Promise that will be resolved with an id object on success, or will be rejected if an error occurs. id is an object with the properties manufacturer, product and if known a human readable name for the associated manufacturer. + */ + deviceId(address: number): Promise; + + /** + * Asynchronous plain I2C read. + * + * @param {number} address + * I2C device address. + * @param {number} length + * The number of bytes to read. + * @param {Buffer} buffer + * The buffer that the data will be written to (must be at least {length} bytes long). + * @return {Promise} + * A Promise that on success will be resolved with an object with a bytesRead property identifying the number of bytes read, and a buffer property that is a reference to the passed in buffer argument. The returned Promise will be rejected if an error occurs. + */ + i2cRead(address: number, length: number, buffer: Buffer): Promise; + + /** + * Asynchronous plain I2C write. + * + * @param {number} address + * I2C device address. + * @param {number} length + * The number of bytes to write. + * @param {Buffer} buffer + * The buffer that the data to write (must contain at least {length} bytes). + * @return {Promise} + * A Promise that on success will be resolved with an object with a bytesWritten property identifying the number of bytes written, and a buffer property that is a reference to the passed in buffer argument. The returned promise will be rejected if an error occurs. + */ + i2cWrite(address: number, length: number, buffer: Buffer): Promise; + + /** + * Asynchronous SMBus read byte. + * + * @param {number} address + * I2C device address. + * @param {number} command + * The command code. + * @return {Promise} + * A Promise that will be resolved with a number representing the byte read on success, or will be rejected if an error occurs. byte is an unsigned integer in the range 0 to 255. + */ + readByte(address: number, command: number): Promise; + + /** + * Asynchronous SMBus read word. + * + * @param {number} address + * I2C device address. + * @param {number} command + * The command code. + * @return {Promise} + * A Promise that will be resolved with a number representing the word read on success, or will be rejected if an error occurs. word is an unsigned integer in the range 0 to 65535. + */ + readWord(address: number, command: number): Promise; + + /** + * Asynchronous I2C block read (not defined by the SMBus specification). + * + * @param {number} address + * I2C device address. + * @param {number} command + * The command code. + * @param {number} length + * The number of bytes to read (max 32). + * @param {Buffer} buffer + * The buffer that the data will be written to (must be at least {length} bytes long). + * @return {Promise} + * A Promise that on success will be resolved with an object with a bytesRead property identifying the number of bytes read, and a buffer property that is a reference to the passed in buffer argument. The returned Promise will be rejected if an error occurs. + */ + readI2cBlock(address: number, command: number, length: number, buffer: Buffer): Promise; + + /** + * Asynchronous SMBus receive byte. + * + * @param {number} address + * I2C device address. + * @return {Promise} + * A Promise that will be resolved with a number representing the byte received on success, or will be rejected if an error occurs. byte is an unsigned integer in the range 0 to 255. + */ + receiveByte(address: number): Promise; + + /** + * Asynchronous SMBus send byte. + * + * @param {number} address + * I2C device address. + * @param {number} byte + * The data byte to send. + * @return {Promise} + * A Promise that will be resolved with no arguments on success, or will be rejected if an error occurs. + */ + sendByte(address: number, byte: number): Promise; + + /** + * Asynchronous SMBus write byte. + * + * @param {number} address + * I2C device address. + * @param {number} command + * The command code. + * @param {number} byte + * The data byte to write. + * @return {Promise} + * A Promise that will be resolved with no arguments on success, or will be rejected if an error occurs. + */ + writeByte(address: number, command: number, byte: number): Promise; + + /** + * Asynchronous SMBus write word. + * + * @param {number} address + * I2C device address. + * @param {number} command + * The command code. + * @param {number} word + * The data word to write. + * @return {Promise} + * A Promise that will be resolved with no arguments on success, or will be rejected if an error occurs. + */ + writeWord(address: number, command: number, word: number): Promise; + + /** + * Asynchronous SMBus quick command. + * + * @param {number} address + * I2C device address. + * @param {number} command + * The command code. + * @param {number} bit + * The data bit to write (0 or 1). + * @return {Promise} + * A Promise that will be resolved with no arguments on success, or will be rejected if an error occurs. + */ + writeQuick(address: number, command: number, bit: number): Promise; + + /** + * Asynchronous I2C block write (not defined by the SMBus specification). + * + * @param {number} address + * I2C device address. + * @param {number} command + * The command code. + * @param {number} length + * The number of bytes to write (max 32). + * @param {Buffer} buffer + * The buffer that the data to write (must contain at least {length} bytes). + * @return {Promise} + * A Promise that on success will be resolved with an object with a bytesWritten property identifying the number of bytes written, and a buffer property that is a reference to the passed in buffer argument. The returned promise will be rejected if an error occurs. + */ + writeI2cBlock(address: number, command: number, length: number, buffer: Buffer): Promise; + + /** + * Return the Bus instance for this PromisifiedBus instance. + * + * @return {I2CBus} + * The Bus instance for this PromisifiedBus instance. + */ + bus(): I2CBus; } /** * Asynchronous open. * * @param {number} busNumber - * The number of the I2C bus/adapter to open, 0 for {/dev/i2c-0}, 1 for {/dev/i2c-1}, etc. + * The number of the I2C bus/adapter to open, 0 for /dev/i2c-0, 1 for /dev/i2c-1, ... + * @param {OpenOptions} [options] + * An optional options object. * @param {CompletionCallback} callback * Completion callback. - * @return {I2cBus} - * A new I2cBus object. + * @return {I2CBus} + * A new Bus object. */ -export function open(busNumber: number, callback: CompletionCallback): I2cBus; +export function open(busNumber: number, callback: CompletionCallback): I2CBus; +export function open(busNumber: number, options: OpenOptions, callback: CompletionCallback): I2CBus; /** * Synchronous open. * * @param {number} busNumber - * The number of the I2C bus/adapter to open, 0 for {/dev/i2c-0}, 1 for {/dev/i2c-1}, etc. - * @return {I2cBus} - * A new I2cBus object. + * The number of the I2C bus/adapter to open, 0 for /dev/i2c-0, 1 for /dev/i2c-1, ... + * @param {OpenOptions} [options] + * An optional options object. + * @return {I2CBus} + * A new Bus object. */ -export function openSync(busNumber: number): I2cBus; +export function openSync(busNumber: number, options?: OpenOptions): I2CBus; + +/** + * Asynchronous open. + * + * @param {number} busNumber + * The number of the I2C bus/adapter to open, 0 for /dev/i2c-0, 1 for /dev/i2c-1, ... + * @param {OpenOptions} [options] + * An optional options object. + * @return {Promise} + * A Promise that, when resolved, yields a PromisifiedBus object. + */ +export function openPromisified(busNumber: number, options?: OpenOptions): Promise;