From d5954a7d92816ab8a45b733ba982490489c58ceb Mon Sep 17 00:00:00 2001 From: AlejandroHerr Date: Sun, 17 Nov 2019 01:08:38 +0100 Subject: [PATCH] feat(bus): update library and dependencies BREAKING CHANGE: Update i2c-bus version to latest, which is already promised. Refactor Bus and Device to classes and remove unnecessary code. --- src/@types/i2c-bus/index.d.ts | 59 +++++ src/index.ts | 6 +- src/lib/Bus.spec.ts | 453 ++++++++++++++++++++++++++++------ src/lib/Bus.ts | 316 +++++++++++++++--------- src/lib/BusError.spec.ts | 19 +- src/lib/BusError.ts | 21 +- src/lib/BusInterface.ts | 29 --- src/lib/Device.spec.ts | 283 +++++++++++++++++---- src/lib/Device.ts | 136 ++++++---- src/lib/DeviceError.spec.ts | 11 - src/lib/DeviceError.ts | 15 -- src/lib/DeviceInterface.ts | 20 -- src/lib/createI2cBusMock.ts | 124 ---------- src/lib/types.ts | 23 -- 14 files changed, 991 insertions(+), 524 deletions(-) create mode 100644 src/@types/i2c-bus/index.d.ts delete mode 100644 src/lib/BusInterface.ts delete mode 100644 src/lib/DeviceError.spec.ts delete mode 100644 src/lib/DeviceError.ts delete mode 100644 src/lib/DeviceInterface.ts delete mode 100644 src/lib/createI2cBusMock.ts delete mode 100644 src/lib/types.ts diff --git a/src/@types/i2c-bus/index.d.ts b/src/@types/i2c-bus/index.d.ts new file mode 100644 index 0000000..e37576b --- /dev/null +++ b/src/@types/i2c-bus/index.d.ts @@ -0,0 +1,59 @@ +declare module 'i2c-bus' { + export interface I2cFuncs { + i2c: boolean; + tenBitAddr: boolean; + protocolMangling: boolean; + smbusPec: boolean; + smbusBlockProcCall: boolean; + smbusQuick: boolean; + smbusReceiveByte: boolean; + smbusSendByte: boolean; + smbusReadByte: boolean; + smbusWriteByte: boolean; + smbusReadWord: boolean; + smbusWriteWord: boolean; + smbusProcCall: boolean; + smbusReadBlock: boolean; + smbusWriteBlock: boolean; + smbusReadI2cBlock: boolean; + smbusWriteI2cBlock: boolean; + } + + export interface I2cReadResponse { + bytesRead: number; + buffer: Buffer; + } + + export interface I2cWriteResponse { + bytesWritten: number; + buffer: Buffer; + } + + export interface PromisifiedBus { + _busNumber: number; + _forceAccess: boolean; + + close(): Promise; + i2cFuncs(): Promise; + + readByte(address: number, command: number): Promise; + readWord(address: number, command: number): Promise; + readI2cBlock(address: number, command: number, length: number, buffer: Buffer): Promise; + receiveByte(address: number): Promise; + + sendByte(address: number, byte: number): Promise; + writeByte(address: number, command: number, byte: number): Promise; + writeWord(address: number, command: number, word: number): Promise; + writeQuick(address: number, bit: 0 | 1): Promise; + writeI2cBlock(address: number, command: number, length: number, buffer: Buffer): Promise; + + i2cRead(address: number, length: number, buffer: Buffer): Promise; + i2cWrite(address: number, length: number, buffer: Buffer): Promise; + + scan(startAddress?: number, endAddress?: number): Promise; + deviceId(address: number): Promise; + } + + // eslint-disable-next-line import/prefer-default-export + export function openPromisified(busNumber: number, options?: { forceAccess: boolean }): Promise; +} diff --git a/src/index.ts b/src/index.ts index 1131426..a434da0 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,9 +1,5 @@ import Bus from './lib/Bus'; import BusError from './lib/BusError'; -import BusInterface from './lib/BusInterface'; -import createI2cBusMock from './lib/createI2cBusMock'; import Device from './lib/Device'; -import DeviceError from './lib/DeviceError'; -import DeviceInterface from './lib/DeviceInterface'; -export { Bus, BusError, BusInterface, createI2cBusMock, Device, DeviceError, DeviceInterface }; +export { Bus, BusError, Device }; diff --git a/src/lib/Bus.spec.ts b/src/lib/Bus.spec.ts index 13c95e0..35e9819 100644 --- a/src/lib/Bus.spec.ts +++ b/src/lib/Bus.spec.ts @@ -1,122 +1,415 @@ +import { PromisifiedBus, openPromisified } from 'i2c-bus'; import Bus from './Bus'; import BusError from './BusError'; -import { I2cBusPromised } from './types'; jest.mock('i2c-bus', () => { - const createI2cBusMock = require('./createI2cBusMock').default; // eslint-disable-line global-require - - return { - open: createI2cBusMock({ - devices: { - 0xc0: Buffer.allocUnsafe(0xff), - 0xff: Buffer.allocUnsafe(0xff), - 0xca: Buffer.allocUnsafe(0xff), - }, - }), - }; + const promisifiedBus = ({ + close: jest.fn(), + i2cFuncs: jest.fn(), + readByte: jest.fn(), + readWord: jest.fn(), + readI2cBlock: jest.fn(), + receiveByte: jest.fn(), + sendByte: jest.fn(), + writeByte: jest.fn(), + writeWord: jest.fn(), + writeQuick: jest.fn(), + writeI2cBlock: jest.fn(), + i2cRead: jest.fn(), + i2cWrite: jest.fn(), + scan: jest.fn(), + deviceId: jest.fn(), + } as unknown) as PromisifiedBus; + + return { openPromisified: (): PromisifiedBus => promisifiedBus }; }); describe('Bus', () => { describe('open', () => { it('should open the bus', async () => { - const bus = Bus({ busNumber: 1 }); + const bus = new Bus({ busNumber: 1 }); + + await bus.open(); + + expect(bus.isOpen).toBeTruthy(); await bus.open(); expect(bus.isOpen).toBeTruthy(); - expect(bus.i2cBus).not.toBeNull(); }); }); - describe('open', () => { - it('should open the bus', async () => { - const bus = Bus({ busNumber: 1 }); - await bus.open(); + describe('close', () => { + it("should call i2c-bus' close functions", async () => { + const i2cBus = await openPromisified(1); + const bus = await new Bus({ busNumber: 1 }).open(); + await bus.close(); + // eslint-disable-next-line @typescript-eslint/unbound-method + expect(i2cBus.close as jest.MockedFunction).toHaveBeenCalledTimes(1); expect(bus.isOpen).toBeFalsy(); - expect(bus.i2cBus).toBeNull(); + }); + + it('should return a BusError if the bus is closed', () => { + const bus = new Bus({ busNumber: 1 }); + + expect(bus.close()).rejects.toEqual(BusError.create('Bus is not open')); }); }); - describe('methods', () => { - it('should throw a Bus error when the bus is not open', () => { - const busNumber = 1; - const bus = Bus({ busNumber }); - expect(bus.i2cFuncs()).rejects.toThrow(new BusError('Bus is not open', busNumber)); - expect(bus.scan()).rejects.toThrow(new BusError('Bus is not open', busNumber)); - expect(bus.i2cRead(0, 1, Buffer.from([]))).rejects.toThrow(new BusError('Bus is not open', busNumber)); - expect(bus.i2cWrite(0, 1, Buffer.from([]))).rejects.toThrow(new BusError('Bus is not open', busNumber)); - expect(bus.receiveByte(0)).rejects.toThrow(new BusError('Bus is not open', busNumber)); - expect(bus.sendByte(0, 0)).rejects.toThrow(new BusError('Bus is not open', busNumber)); - expect(bus.readByte(0, 0)).rejects.toThrow(new BusError('Bus is not open', busNumber)); - expect(bus.readWord(0, 0)).rejects.toThrow(new BusError('Bus is not open', busNumber)); - expect(bus.readI2cBlock(0, 0, 1, Buffer.from([]))).rejects.toThrow(new BusError('Bus is not open', busNumber)); - expect(bus.writeByte(0, 0, 1)).rejects.toThrow(new BusError('Bus is not open', busNumber)); - expect(bus.writeWord(0, 0, 1)).rejects.toThrow(new BusError('Bus is not open', busNumber)); - expect(bus.writeI2cBlock(0, 0, 1, Buffer.from([]))).rejects.toThrow(new BusError('Bus is not open', busNumber)); + describe('i2cFuncs', () => { + it("should call i2c-bus' i2cFuncs functions", async () => { + const i2cBus = await openPromisified(1); + const bus = await new Bus({ busNumber: 1 }).open(); - expect(bus.close()).rejects.toThrow(new BusError('Bus is not open', busNumber)); + await bus.i2cFuncs(); + + // eslint-disable-next-line @typescript-eslint/unbound-method + expect(i2cBus.i2cFuncs as jest.MockedFunction).toHaveBeenCalledTimes(1); }); - it('should call promised async function', async () => { - const busNumber = 1; - const bus = Bus({ busNumber }); - await bus.open(); + it('should return a BusError if the bus is closed', () => { + const bus = new Bus({ busNumber: 1 }); - const { i2cBus } = bus; + expect(bus.i2cFuncs()).rejects.toEqual(BusError.create('Bus is not open')); + }); + }); - (i2cBus as I2cBusPromised).i2cFuncsAsync = jest.fn(); - await bus.i2cFuncs(); - expect((i2cBus as I2cBusPromised).i2cFuncsAsync).toHaveBeenCalled(); + describe('readByte', () => { + const address = 0x1; + const command = 0x2; + it("should call i2c-bus' readByte functions", async () => { + const i2cBus = await openPromisified(1); + const bus = await new Bus({ busNumber: 1 }).open(); - (i2cBus as I2cBusPromised).scanAsync = jest.fn(); - await bus.scan(); - expect((i2cBus as I2cBusPromised).scanAsync).toHaveBeenCalled(); + await bus.readByte(address, command); - (i2cBus as I2cBusPromised).i2cReadAsync = jest.fn(); - await bus.i2cRead(0, 1, Buffer.from([])); - expect((i2cBus as I2cBusPromised).i2cReadAsync).toHaveBeenCalled(); + // eslint-disable-next-line @typescript-eslint/unbound-method + expect(i2cBus.readByte as jest.MockedFunction).toHaveBeenCalledTimes(1); + // eslint-disable-next-line @typescript-eslint/unbound-method + expect(i2cBus.readByte as jest.MockedFunction).toHaveBeenCalledWith(address, command); + }); - (i2cBus as I2cBusPromised).i2cWriteAsync = jest.fn(); - await bus.i2cWrite(0, 1, Buffer.from([])); - expect((i2cBus as I2cBusPromised).i2cWriteAsync).toHaveBeenCalled(); + it('should return a BusError if the bus is closed', () => { + const bus = new Bus({ busNumber: 1 }); - (i2cBus as I2cBusPromised).receiveByteAsync = jest.fn(); - await bus.receiveByte(0); - expect((i2cBus as I2cBusPromised).receiveByteAsync).toHaveBeenCalled(); + expect(bus.readByte(address, command)).rejects.toEqual(BusError.create('Bus is not open')); + }); + }); - (i2cBus as I2cBusPromised).sendByteAsync = jest.fn(); - await bus.sendByte(0, 0); - expect((i2cBus as I2cBusPromised).sendByteAsync).toHaveBeenCalled(); + describe('readWord', () => { + const address = 0x1; + const command = 0x2; + it("should call i2c-bus' readWord functions", async () => { + const i2cBus = await openPromisified(1); + const bus = await new Bus({ busNumber: 1 }).open(); - (i2cBus as I2cBusPromised).readByteAsync = jest.fn(); - await bus.readByte(0, 0); - expect((i2cBus as I2cBusPromised).readByteAsync).toHaveBeenCalled(); + await bus.readWord(address, command); - (i2cBus as I2cBusPromised).readWordAsync = jest.fn(); - await bus.readWord(0, 0); - expect((i2cBus as I2cBusPromised).readWordAsync).toHaveBeenCalled(); + // eslint-disable-next-line @typescript-eslint/unbound-method + expect(i2cBus.readWord as jest.MockedFunction).toHaveBeenCalledTimes(1); + // eslint-disable-next-line @typescript-eslint/unbound-method + expect(i2cBus.readWord as jest.MockedFunction).toHaveBeenCalledWith(address, command); + }); - (i2cBus as I2cBusPromised).readI2cBlockAsync = jest.fn(); - await bus.readI2cBlock(0, 0, 1, Buffer.from([])); - expect((i2cBus as I2cBusPromised).readI2cBlockAsync).toHaveBeenCalled(); + it('should return a BusError if the bus is closed', () => { + const bus = new Bus({ busNumber: 1 }); - (i2cBus as I2cBusPromised).writeByteAsync = jest.fn(); - await bus.writeByte(0, 0, 1); - expect((i2cBus as I2cBusPromised).writeByteAsync).toHaveBeenCalled(); + expect(bus.readWord(address, command)).rejects.toEqual(BusError.create('Bus is not open')); + }); + }); - (i2cBus as I2cBusPromised).writeWordAsync = jest.fn(); - await bus.writeWord(0, 0, 1); - expect((i2cBus as I2cBusPromised).writeWordAsync).toHaveBeenCalled(); + describe('readI2cBlock', () => { + const address = 0x1; + const command = 0x2; + const length = 3; + const buffer = Buffer.alloc(0); + it("should call i2c-bus' readI2cBlock functions", async () => { + const i2cBus = await openPromisified(1); + const bus = await new Bus({ busNumber: 1 }).open(); - (i2cBus as I2cBusPromised).writeI2cBlockAsync = jest.fn(); - await bus.writeI2cBlock(0, 0, 1, Buffer.from([])); - expect((i2cBus as I2cBusPromised).writeI2cBlockAsync).toHaveBeenCalled(); + await bus.readI2cBlock(address, command, length, buffer); - (i2cBus as I2cBusPromised).closeAsync = jest.fn(); - await bus.close(); - expect((i2cBus as I2cBusPromised).closeAsync).toHaveBeenCalled(); + // eslint-disable-next-line @typescript-eslint/unbound-method + expect(i2cBus.readI2cBlock as jest.MockedFunction).toHaveBeenCalledTimes(1); + // eslint-disable-next-line @typescript-eslint/unbound-method + expect(i2cBus.readI2cBlock as jest.MockedFunction).toHaveBeenCalledWith( + address, + command, + length, + buffer, + ); + }); + + it('should return a BusError if the bus is closed', () => { + const bus = new Bus({ busNumber: 1 }); + + expect(bus.readI2cBlock(address, command, length, buffer)).rejects.toEqual(BusError.create('Bus is not open')); + }); + }); + + describe('receiveByte', () => { + const address = 0x1; + it("should call i2c-bus' receiveByte functions", async () => { + const i2cBus = await openPromisified(1); + const bus = await new Bus({ busNumber: 1 }).open(); + + await bus.receiveByte(address); + + // eslint-disable-next-line @typescript-eslint/unbound-method + expect(i2cBus.receiveByte as jest.MockedFunction).toHaveBeenCalledTimes(1); + // eslint-disable-next-line @typescript-eslint/unbound-method + expect(i2cBus.receiveByte as jest.MockedFunction).toHaveBeenCalledWith(address); + }); + + it('should return a BusError if the bus is closed', () => { + const bus = new Bus({ busNumber: 1 }); + + expect(bus.receiveByte(address)).rejects.toEqual(BusError.create('Bus is not open')); + }); + }); + + describe('sendByte', () => { + const address = 0x1; + const byte = 0x2; + it("should call i2c-bus' sendByte functions", async () => { + const i2cBus = await openPromisified(1); + const bus = await new Bus({ busNumber: 1 }).open(); + + await bus.sendByte(address, byte); + + // eslint-disable-next-line @typescript-eslint/unbound-method + expect(i2cBus.sendByte as jest.MockedFunction).toHaveBeenCalledTimes(1); + // eslint-disable-next-line @typescript-eslint/unbound-method + expect(i2cBus.sendByte as jest.MockedFunction).toHaveBeenCalledWith(address, byte); + }); + + it('should return a BusError if the bus is closed', () => { + const bus = new Bus({ busNumber: 1 }); + + expect(bus.sendByte(address, byte)).rejects.toEqual(BusError.create('Bus is not open')); + }); + }); + + describe('writeByte', () => { + const address = 0x1; + const command = 0x2; + const byte = 0x3; + it("should call i2c-bus' writeByte functions", async () => { + const i2cBus = await openPromisified(1); + const bus = await new Bus({ busNumber: 1 }).open(); + + await bus.writeByte(address, command, byte); + + // eslint-disable-next-line @typescript-eslint/unbound-method + expect(i2cBus.writeByte as jest.MockedFunction).toHaveBeenCalledTimes(1); + // eslint-disable-next-line @typescript-eslint/unbound-method + expect(i2cBus.writeByte as jest.MockedFunction).toHaveBeenCalledWith( + address, + command, + byte, + ); + }); + + it('should return a BusError if the bus is closed', () => { + const bus = new Bus({ busNumber: 1 }); + + expect(bus.writeByte(address, command, byte)).rejects.toEqual(BusError.create('Bus is not open')); + }); + }); + + describe('writeWord', () => { + const address = 0x1; + const command = 0x2; + const word = 0x3; + it("should call i2c-bus' writeWord functions", async () => { + const i2cBus = await openPromisified(1); + const bus = await new Bus({ busNumber: 1 }).open(); + + await bus.writeWord(address, command, word); + + // eslint-disable-next-line @typescript-eslint/unbound-method + expect(i2cBus.writeWord as jest.MockedFunction).toHaveBeenCalledTimes(1); + // eslint-disable-next-line @typescript-eslint/unbound-method + expect(i2cBus.writeWord as jest.MockedFunction).toHaveBeenCalledWith( + address, + command, + word, + ); + }); + + it('should return a BusError if the bus is closed', () => { + const bus = new Bus({ busNumber: 1 }); + + expect(bus.writeWord(address, command, word)).rejects.toEqual(BusError.create('Bus is not open')); + }); + }); + + describe('writeQuick', () => { + const address = 0x1; + const bit = 0x0; + it("should call i2c-bus' writeQuick functions", async () => { + const i2cBus = await openPromisified(1); + const bus = await new Bus({ busNumber: 1 }).open(); + + await bus.writeQuick(address, bit); + + // eslint-disable-next-line @typescript-eslint/unbound-method + expect(i2cBus.writeQuick as jest.MockedFunction).toHaveBeenCalledTimes(1); + // eslint-disable-next-line @typescript-eslint/unbound-method + expect(i2cBus.writeQuick as jest.MockedFunction).toHaveBeenCalledWith(address, bit); + }); + + it('should return a BusError if the bus is closed', () => { + const bus = new Bus({ busNumber: 1 }); + + expect(bus.writeQuick(address, bit)).rejects.toEqual(BusError.create('Bus is not open')); + }); + }); + + describe('writeI2cBlock', () => { + const address = 0x1; + const command = 0x2; + const length = 3; + const buffer = Buffer.alloc(0); + it("should call i2c-bus' writeI2cBlock functions", async () => { + const i2cBus = await openPromisified(1); + const bus = await new Bus({ busNumber: 1 }).open(); + + await bus.writeI2cBlock(address, command, length, buffer); + + // eslint-disable-next-line @typescript-eslint/unbound-method + expect(i2cBus.writeI2cBlock as jest.MockedFunction).toHaveBeenCalledTimes(1); + // eslint-disable-next-line @typescript-eslint/unbound-method + expect(i2cBus.writeI2cBlock as jest.MockedFunction).toHaveBeenCalledWith( + address, + command, + length, + buffer, + ); + }); + it('should return a BusError if the bus is closed', () => { + const bus = new Bus({ busNumber: 1 }); + + expect(bus.writeI2cBlock(address, command, length, buffer)).rejects.toEqual(BusError.create('Bus is not open')); + }); + }); + + describe('i2cRead', () => { + const address = 0x1; + const length = 3; + const buffer = Buffer.alloc(0); + it("should call i2c-bus' i2cRead functions", async () => { + const i2cBus = await openPromisified(1); + const bus = await new Bus({ busNumber: 1 }).open(); + + await bus.i2cRead(address, length, buffer); + + // eslint-disable-next-line @typescript-eslint/unbound-method + expect(i2cBus.i2cRead as jest.MockedFunction).toHaveBeenCalledTimes(1); + // eslint-disable-next-line @typescript-eslint/unbound-method + expect(i2cBus.i2cRead as jest.MockedFunction).toHaveBeenCalledWith( + address, + length, + buffer, + ); + }); + + it('should return a BusError if the bus is closed', () => { + const bus = new Bus({ busNumber: 1 }); + + expect(bus.i2cRead(address, length, buffer)).rejects.toEqual(BusError.create('Bus is not open')); + }); + }); + + describe('i2cWrite', () => { + const address = 0x1; + const length = 3; + const buffer = Buffer.alloc(0); + it("should call i2c-bus' i2cWrite functions", async () => { + const i2cBus = await openPromisified(1); + const bus = await new Bus({ busNumber: 1 }).open(); + + await bus.i2cWrite(address, length, buffer); + + // eslint-disable-next-line @typescript-eslint/unbound-method + expect(i2cBus.i2cWrite as jest.MockedFunction).toHaveBeenCalledTimes(1); + // eslint-disable-next-line @typescript-eslint/unbound-method + expect(i2cBus.i2cWrite as jest.MockedFunction).toHaveBeenCalledWith( + address, + + length, + buffer, + ); + }); + + it('should return a BusError if the bus is closed', () => { + const bus = new Bus({ busNumber: 1 }); + + expect(bus.i2cWrite(address, length, buffer)).rejects.toEqual(BusError.create('Bus is not open')); + }); + }); + + describe('scan', () => { + const startAddress = 0x1; + const endAddress = 0x2; + it("should call i2c-bus' scan functions", async () => { + const i2cBus = await openPromisified(1); + const bus = await new Bus({ busNumber: 1 }).open(); + + await bus.scan(startAddress, endAddress); + + // eslint-disable-next-line @typescript-eslint/unbound-method + expect(i2cBus.scan as jest.MockedFunction).toHaveBeenCalledTimes(1); + // eslint-disable-next-line @typescript-eslint/unbound-method + expect(i2cBus.scan as jest.MockedFunction).toHaveBeenCalledWith(startAddress, endAddress); + }); + + it('should return a BusError if the bus is closed', () => { + const bus = new Bus({ busNumber: 1 }); + + expect(bus.scan(startAddress, endAddress)).rejects.toEqual(BusError.create('Bus is not open')); + }); + }); + + describe('deviceId', () => { + const address = 0x1; + it("should call i2c-bus' deviceId functions", async () => { + const i2cBus = await openPromisified(1); + const bus = await new Bus({ busNumber: 1 }).open(); + + await bus.deviceId(address); + + // eslint-disable-next-line @typescript-eslint/unbound-method + expect(i2cBus.deviceId as jest.MockedFunction).toHaveBeenCalledTimes(1); + // eslint-disable-next-line @typescript-eslint/unbound-method + expect(i2cBus.deviceId as jest.MockedFunction).toHaveBeenCalledWith(address); + }); + + it('should return a BusError if the bus is closed', () => { + const bus = new Bus({ busNumber: 1 }); + + expect(bus.deviceId(address)).rejects.toEqual(BusError.create('Bus is not open')); + }); + }); + + describe('static create', () => { + it('should create a Bus instance', () => { + const bus = Bus.create({ busNumber: 1 }); + + expect(bus).toBeInstanceOf(Bus); + expect(bus.busNumber).toEqual(1); + }); + }); + + describe('static createAndOpen', () => { + it('should create a Bus instance', async () => { + const bus = await Bus.createAndOpen({ busNumber: 1 }); + + expect(bus).toBeInstanceOf(Bus); + expect(bus.busNumber).toBe(1); + expect(bus.isOpen).toBeTruthy(); }); }); }); diff --git a/src/lib/Bus.ts b/src/lib/Bus.ts index f46e85f..2fdca78 100644 --- a/src/lib/Bus.ts +++ b/src/lib/Bus.ts @@ -1,140 +1,226 @@ -import { promisifyAll } from 'bluebird'; -import { open as openI2cBus } from 'i2c-bus'; +import { openPromisified, PromisifiedBus, I2cFuncs, I2cReadResponse, I2cWriteResponse } from 'i2c-bus'; import BusError from './BusError'; -import BusInterface from './BusInterface'; -import { I2cBusPromised } from './types'; - -const Bus = ({ busNumber = 1, openBus = openI2cBus } = {}): BusInterface => { - let i2cBus: I2cBusPromised | null = null; - let isOpen: boolean = false; - - return { - get busNumber() { - return busNumber; - }, - get i2cBus() { - return i2cBus; - }, - get isOpen() { - return isOpen; - }, - - open() { - return new Promise((resolve, reject) => { - i2cBus = promisifyAll(openBus(this.busNumber, (error: Error) => { - if (error) { - reject(`Error opening i2c bus: ${error.message}`); - } - - isOpen = true; - - resolve(this); - }) as I2cBusPromised); - }); - }, - async close() { - if (!i2cBus || !isOpen) { - throw new BusError('Bus is not open', busNumber); + +export default class Bus { + private i2cBus!: PromisifiedBus; + + readonly busNumber: number; + + isOpen = false; + + constructor({ busNumber }: { busNumber: number }) { + this.busNumber = busNumber; + } + + private guardAgainstClosedBus(): void { + if (!this.isOpen) { + throw BusError.create('Bus is not open'); + } + } + + async open(): Promise { + try { + if (!this.isOpen) { + this.i2cBus = await openPromisified(this.busNumber); + this.isOpen = true; } - await i2cBus.closeAsync(); + return this; + } catch (error) { + throw BusError.createFromError(error); + } + } - isOpen = false; - i2cBus = null; + async close(): Promise { + this.guardAgainstClosedBus(); + + try { + await this.i2cBus.close(); + + this.isOpen = false; return this; - }, + } catch (error) { + throw BusError.createFromError(error); + } + } - async i2cFuncs() { - if (!i2cBus || !isOpen) { - throw new BusError('Bus is not open', busNumber); - } + async i2cFuncs(): Promise { + this.guardAgainstClosedBus(); - return i2cBus.i2cFuncsAsync(); - }, - async scan() { - if (!i2cBus || !isOpen) { - throw new BusError('Bus is not open', busNumber); - } + try { + const result = await this.i2cBus.i2cFuncs(); - return i2cBus.scanAsync(); - }, + return result; + } catch (error) { + throw BusError.createFromError(error); + } + } - async i2cRead(address: number, length: number, buffer: Buffer) { - if (!i2cBus || !isOpen) { - throw new BusError('Bus is not open', busNumber); - } + async readByte(address: number, command: number): Promise { + this.guardAgainstClosedBus(); - return i2cBus.i2cReadAsync(address, length, buffer); - }, - async i2cWrite(address: number, length: number, buffer: Buffer) { - if (!i2cBus || !isOpen) { - throw new BusError('Bus is not open', busNumber); - } + try { + const result = await this.i2cBus.readByte(address, command); - return i2cBus.i2cWriteAsync(address, length, buffer); - }, + return result; + } catch (error) { + throw BusError.createFromError(error); + } + } - async receiveByte(address: number) { - if (!i2cBus || !isOpen) { - throw new BusError('Bus is not open', busNumber); - } + async readWord(address: number, command: number): Promise { + this.guardAgainstClosedBus(); - return i2cBus.receiveByteAsync(address); - }, - async sendByte(address: number, byte: number) { - if (!i2cBus || !isOpen) { - throw new BusError('Bus is not open', busNumber); - } + try { + const result = await this.i2cBus.readWord(address, command); - return i2cBus.sendByteAsync(address, byte); - }, + return result; + } catch (error) { + throw BusError.createFromError(error); + } + } - async readByte(address: number, command: number) { - if (!i2cBus || !isOpen) { - throw new BusError('Bus is not open', busNumber); - } + async readI2cBlock(address: number, command: number, length: number, buffer: Buffer): Promise { + this.guardAgainstClosedBus(); - return i2cBus.readByteAsync(address, command); - }, - async readWord(address: number, command: number) { - if (!i2cBus || !isOpen) { - throw new BusError('Bus is not open', busNumber); - } + try { + const result = await this.i2cBus.readI2cBlock(address, command, length, buffer); - return i2cBus.readWordAsync(address, command); - }, - async readI2cBlock(address: number, command: number, length: number, buffer: Buffer) { - if (!i2cBus || !isOpen) { - throw new BusError('Bus is not open', busNumber); - } + return result; + } catch (error) { + throw BusError.createFromError(error); + } + } - return i2cBus.readI2cBlockAsync(address, command, length, buffer); - }, + async receiveByte(address: number): Promise { + this.guardAgainstClosedBus(); - async writeByte(address: number, command: number, byte: number) { - if (!i2cBus || !isOpen) { - throw new BusError('Bus is not open', busNumber); - } + try { + const result = await this.i2cBus.receiveByte(address); - return i2cBus.writeByteAsync(address, command, byte); - }, - async writeWord(address: number, command: number, word: number) { - if (!i2cBus || !isOpen) { - throw new BusError('Bus is not open', busNumber); - } + return result; + } catch (error) { + throw BusError.createFromError(error); + } + } - return i2cBus.writeWordAsync(address, command, word); - }, - async writeI2cBlock(address: number, command: number, length: number, buffer: Buffer) { - if (!i2cBus || !isOpen) { - throw new BusError('Bus is not open', busNumber); - } + async sendByte(address: number, byte: number): Promise { + this.guardAgainstClosedBus(); + + try { + await this.i2cBus.sendByte(address, byte); + + return this; + } catch (error) { + throw BusError.createFromError(error); + } + } + + async writeByte(address: number, command: number, byte: number): Promise { + this.guardAgainstClosedBus(); + + try { + await this.i2cBus.writeByte(address, command, byte); + + return this; + } catch (error) { + throw BusError.createFromError(error); + } + } + + async writeWord(address: number, command: number, word: number): Promise { + this.guardAgainstClosedBus(); + + try { + await this.i2cBus.writeWord(address, command, word); + + return this; + } catch (error) { + throw BusError.createFromError(error); + } + } + + async writeQuick(address: number, bit: 0 | 1): Promise { + this.guardAgainstClosedBus(); + + try { + await this.i2cBus.writeQuick(address, bit); + + return this; + } catch (error) { + throw BusError.createFromError(error); + } + } + + async writeI2cBlock(address: number, command: number, length: number, buffer: Buffer): Promise { + this.guardAgainstClosedBus(); + + try { + const result = await this.i2cBus.writeI2cBlock(address, command, length, buffer); + + return result; + } catch (error) { + throw BusError.createFromError(error); + } + } + + async i2cRead(address: number, length: number, buffer: Buffer): Promise { + this.guardAgainstClosedBus(); + + try { + const result = await this.i2cBus.i2cRead(address, length, buffer); + + return result; + } catch (error) { + throw BusError.createFromError(error); + } + } + + async i2cWrite(address: number, length: number, buffer: Buffer): Promise { + this.guardAgainstClosedBus(); + + try { + const result = await this.i2cBus.i2cWrite(address, length, buffer); + + return result; + } catch (error) { + throw BusError.createFromError(error); + } + } + + async scan(startAddress?: number, endAddress?: number): Promise { + this.guardAgainstClosedBus(); + + try { + const result = await this.i2cBus.scan(startAddress, endAddress); + + return result; + } catch (error) { + throw BusError.createFromError(error); + } + } + + async deviceId(address: number): Promise { + this.guardAgainstClosedBus(); + + try { + const result = await this.i2cBus.deviceId(address); + + return result; + } catch (error) { + throw BusError.createFromError(error); + } + } + + static create({ busNumber }: { busNumber: number }): Bus { + return new Bus({ busNumber }); + } - return i2cBus.writeI2cBlockAsync(address, command, length, buffer); - }, - }; -}; + static createAndOpen({ busNumber }: { busNumber: number }): Promise { + const bus = new Bus({ busNumber }); -export default Bus; + return bus.open(); + } +} diff --git a/src/lib/BusError.spec.ts b/src/lib/BusError.spec.ts index e169104..1d21d0e 100644 --- a/src/lib/BusError.spec.ts +++ b/src/lib/BusError.spec.ts @@ -1,10 +1,21 @@ import BusError from './BusError'; describe('BusError', () => { - it('should instantiate error with bus number and message', () => { - const error = new BusError('Test error', 2); + describe('static create', () => { + it('should create an instance of BusError with the message ', () => { + const errorMessage = 'Test Error'; + const busError = BusError.create(errorMessage); - expect(error.message).toBe('Test error'); - expect(error.busNumber).toBe(2); + expect(busError.message).toBe(errorMessage); + }); + }); + describe('static createFromError', () => { + it('should create an instance of BusError with the message and stack of the previous error', () => { + const error = new Error('Test Error'); + const busError = BusError.createFromError(error); + + expect(busError.message).toBe(error.message); + expect(busError.stack).toBe(error.stack); + }); }); }); diff --git a/src/lib/BusError.ts b/src/lib/BusError.ts index 3093817..bd0c847 100644 --- a/src/lib/BusError.ts +++ b/src/lib/BusError.ts @@ -1,13 +1,22 @@ export default class BusError extends Error { - public busNumber: number; + static create(message: string): BusError { + const busError = new BusError(message); - constructor(message: string, busNumber: number) { - super(message); + if (typeof Error.captureStackTrace === 'function') { + // eslint-disable-next-line @typescript-eslint/unbound-method + Error.captureStackTrace(busError, BusError.create); + } else { + busError.stack = new Error(message).stack; + } - this.name = this.constructor.name; + return busError; + } + + static createFromError(error: Error): BusError { + const busError = new BusError(error.message); - Error.captureStackTrace(this, BusError); + busError.stack = error.stack; - this.busNumber = busNumber; + return busError; } } diff --git a/src/lib/BusInterface.ts b/src/lib/BusInterface.ts deleted file mode 100644 index e7db0af..0000000 --- a/src/lib/BusInterface.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { I2cBusFuncs } from 'i2c-bus'; - -import { I2cBusPromised } from './types'; - -export default interface BusInterface { - readonly busNumber: number; - readonly i2cBus: I2cBusPromised | null; - readonly isOpen: boolean; - - open(): Promise; - close(): Promise; - - i2cFuncs(): Promise; - scan(): Promise; - - i2cRead(address: number, length: number, buffer: Buffer): Promise; - i2cWrite(address: number, length: number, buffer: Buffer): Promise; - - receiveByte(address: number): Promise; - sendByte(address: number, byte: number): Promise; - - readByte(address: number, command: number): Promise; - readI2cBlock(address: number, command: number, length: number, buffer: Buffer): Promise; - readWord(address: number, command: number): Promise; - - writeByte(address: number, command: number, byte: number): Promise; - writeWord(address: number, command: number, word: number): Promise; - writeI2cBlock(address: number, command: number, length: number, buffer: Buffer): Promise; -} diff --git a/src/lib/Device.spec.ts b/src/lib/Device.spec.ts index 970431b..83e37ac 100644 --- a/src/lib/Device.spec.ts +++ b/src/lib/Device.spec.ts @@ -1,65 +1,256 @@ +import { PromisifiedBus, openPromisified } from 'i2c-bus'; + import Bus from './Bus'; import Device from './Device'; jest.mock('i2c-bus', () => { - const createI2cBusMock = require('./createI2cBusMock').default; // eslint-disable-line global-require - - return { - open: createI2cBusMock({ - devices: { - 0xab: Buffer.allocUnsafe(0xff), - }, - }), - }; + const promisifiedBus = ({ + close: jest.fn(), + i2cFuncs: jest.fn(), + readByte: jest.fn(), + readWord: jest.fn(), + readI2cBlock: jest.fn(), + receiveByte: jest.fn(), + sendByte: jest.fn(), + writeByte: jest.fn(), + writeWord: jest.fn(), + writeQuick: jest.fn(), + writeI2cBlock: jest.fn(), + i2cRead: jest.fn(), + i2cWrite: jest.fn(), + scan: jest.fn(), + deviceId: jest.fn(), + } as unknown) as PromisifiedBus; + + return { openPromisified: (): PromisifiedBus => promisifiedBus }; }); -describe('Device', () => { - it('should call promised async function', async () => { - const busNumber = 1; - const bus = Bus({ busNumber }); - const address = 0xab; - const device = Device({ address, bus }); +const setup = async (): Promise<{ + busNumber: number; + address: number; + i2cBus: PromisifiedBus; + bus: Bus; + device: Device; +}> => { + const busNumber = 1; + const address = 0xff; + + const i2cBus = await openPromisified(busNumber); + const bus = await Bus.createAndOpen({ busNumber }); + const device = Device.create({ bus, address }); + + return { busNumber, address, i2cBus, bus, device }; +}; + +describe('Bus', () => { + describe('readByte', () => { + const command = 0x2; + it("should call i2c-bus' readByte function through the bus", async () => { + const { address, i2cBus, device } = await setup(); + + await device.readByte(command); + + // eslint-disable-next-line @typescript-eslint/unbound-method + expect(i2cBus.readByte as jest.MockedFunction).toHaveBeenCalledTimes(1); + // eslint-disable-next-line @typescript-eslint/unbound-method + expect(i2cBus.readByte as jest.MockedFunction).toHaveBeenCalledWith(address, command); + }); + }); + + describe('readWord', () => { + const command = 0x2; + it("should call i2c-bus' readWord function through the bus", async () => { + const { address, i2cBus, device } = await setup(); + + await device.readWord(command); + + // eslint-disable-next-line @typescript-eslint/unbound-method + expect(i2cBus.readWord as jest.MockedFunction).toHaveBeenCalledTimes(1); + // eslint-disable-next-line @typescript-eslint/unbound-method + expect(i2cBus.readWord as jest.MockedFunction).toHaveBeenCalledWith(address, command); + }); + }); + + describe('readI2cBlock', () => { + const command = 0x2; + const length = 3; + const buffer = Buffer.alloc(0); + it("should call i2c-bus' readI2cBlock function through the bus", async () => { + const { address, i2cBus, device } = await setup(); + + await device.readI2cBlock(command, length, buffer); - await bus.open(); + // eslint-disable-next-line @typescript-eslint/unbound-method + expect(i2cBus.readI2cBlock as jest.MockedFunction).toHaveBeenCalledTimes(1); + // eslint-disable-next-line @typescript-eslint/unbound-method + expect(i2cBus.readI2cBlock as jest.MockedFunction).toHaveBeenCalledWith( + address, + command, + length, + buffer, + ); + }); + }); + + describe('receiveByte', () => { + it("should call i2c-bus' receiveByte function through the bus", async () => { + const { address, i2cBus, device } = await setup(); - const spyOnI2cRead = jest.spyOn(bus, 'i2cRead'); - await device.i2cRead(1, Buffer.from([])); - expect(spyOnI2cRead).toHaveBeenCalledWith(address, 1, Buffer.from([])); + await device.receiveByte(); - const spyOnI2cWrite = jest.spyOn(bus, 'i2cWrite'); - await device.i2cWrite(1, Buffer.from([])); - expect(spyOnI2cWrite).toHaveBeenCalledWith(address, 1, Buffer.from([])); + // eslint-disable-next-line @typescript-eslint/unbound-method + expect(i2cBus.receiveByte as jest.MockedFunction).toHaveBeenCalledTimes(1); + // eslint-disable-next-line @typescript-eslint/unbound-method + expect(i2cBus.receiveByte as jest.MockedFunction).toHaveBeenCalledWith(address); + }); + }); - const spyOnReceiveByte = jest.spyOn(bus, 'receiveByte'); - await device.receiveByte(); - expect(spyOnReceiveByte).toHaveBeenCalledWith(address); + describe('sendByte', () => { + const byte = 0x2; + it("should call i2c-bus' sendByte function through the bus", async () => { + const { address, i2cBus, device } = await setup(); - const spyOnSendByte = jest.spyOn(bus, 'sendByte'); - await device.sendByte(1); - expect(spyOnSendByte).toHaveBeenCalledWith(address, 1); + await device.sendByte(byte); - const spyOnReadByte = jest.spyOn(bus, 'readByte'); - await device.readByte(1); - expect(spyOnReadByte).toHaveBeenCalledWith(address, 1); + // eslint-disable-next-line @typescript-eslint/unbound-method + expect(i2cBus.sendByte as jest.MockedFunction).toHaveBeenCalledTimes(1); + // eslint-disable-next-line @typescript-eslint/unbound-method + expect(i2cBus.sendByte as jest.MockedFunction).toHaveBeenCalledWith(address, byte); + }); + }); + + describe('writeByte', () => { + const command = 0x2; + const byte = 0x3; + it("should call i2c-bus' writeByte function through the bus", async () => { + const { address, i2cBus, device } = await setup(); + + await device.writeByte(command, byte); + + // eslint-disable-next-line @typescript-eslint/unbound-method + expect(i2cBus.writeByte as jest.MockedFunction).toHaveBeenCalledTimes(1); + // eslint-disable-next-line @typescript-eslint/unbound-method + expect(i2cBus.writeByte as jest.MockedFunction).toHaveBeenCalledWith( + address, + command, + byte, + ); + }); + }); - const spyOnReadWord = jest.spyOn(bus, 'readWord'); - await device.readWord(1); - expect(spyOnReadWord).toHaveBeenCalledWith(address, 1); + describe('writeWord', () => { + const command = 0x2; + const word = 0x3; + it("should call i2c-bus' writeWord function through the bus", async () => { + const { address, i2cBus, device } = await setup(); - const spyOnReadI2cBlock = jest.spyOn(bus, 'readI2cBlock'); - await device.readI2cBlock(1, 2, Buffer.from([])); - expect(spyOnReadI2cBlock).toHaveBeenCalledWith(address, 1, 2, Buffer.from([])); + await device.writeWord(command, word); - const spyOnWriteByte = jest.spyOn(bus, 'writeByte'); - await device.writeByte(1, 2); - expect(spyOnWriteByte).toHaveBeenCalledWith(address, 1, 2); + // eslint-disable-next-line @typescript-eslint/unbound-method + expect(i2cBus.writeWord as jest.MockedFunction).toHaveBeenCalledTimes(1); + // eslint-disable-next-line @typescript-eslint/unbound-method + expect(i2cBus.writeWord as jest.MockedFunction).toHaveBeenCalledWith( + address, + command, + word, + ); + }); + }); + + describe('writeQuick', () => { + const bit = 0x0; + it("should call i2c-bus' writeQuick function through the bus", async () => { + const { address, i2cBus, device } = await setup(); + + await device.writeQuick(bit); + + // eslint-disable-next-line @typescript-eslint/unbound-method + expect(i2cBus.writeQuick as jest.MockedFunction).toHaveBeenCalledTimes(1); + // eslint-disable-next-line @typescript-eslint/unbound-method + expect(i2cBus.writeQuick as jest.MockedFunction).toHaveBeenCalledWith(address, bit); + }); + }); + + describe('writeI2cBlock', () => { + const command = 0x2; + const length = 3; + const buffer = Buffer.alloc(0); + it("should call i2c-bus' writeI2cBlock function through the bus", async () => { + const { address, i2cBus, device } = await setup(); + + await device.writeI2cBlock(command, length, buffer); + + // eslint-disable-next-line @typescript-eslint/unbound-method + expect(i2cBus.writeI2cBlock as jest.MockedFunction).toHaveBeenCalledTimes(1); + // eslint-disable-next-line @typescript-eslint/unbound-method + expect(i2cBus.writeI2cBlock as jest.MockedFunction).toHaveBeenCalledWith( + address, + command, + length, + buffer, + ); + }); + }); + + describe('i2cRead', () => { + const length = 3; + const buffer = Buffer.alloc(0); + it("should call i2c-bus' i2cRead function through the bus", async () => { + const { address, i2cBus, device } = await setup(); + + await device.i2cRead(length, buffer); + + // eslint-disable-next-line @typescript-eslint/unbound-method + expect(i2cBus.i2cRead as jest.MockedFunction).toHaveBeenCalledTimes(1); + // eslint-disable-next-line @typescript-eslint/unbound-method + expect(i2cBus.i2cRead as jest.MockedFunction).toHaveBeenCalledWith( + address, + length, + buffer, + ); + }); + }); + + describe('i2cWrite', () => { + const length = 3; + const buffer = Buffer.alloc(0); + it("should call i2c-bus' i2cWrite function through the bus", async () => { + const { address, i2cBus, device } = await setup(); + + await device.i2cWrite(length, buffer); + + // eslint-disable-next-line @typescript-eslint/unbound-method + expect(i2cBus.i2cWrite as jest.MockedFunction).toHaveBeenCalledTimes(1); + // eslint-disable-next-line @typescript-eslint/unbound-method + expect(i2cBus.i2cWrite as jest.MockedFunction).toHaveBeenCalledWith( + address, + length, + buffer, + ); + }); + }); + + describe('deviceId', () => { + it("should call i2c-bus' deviceId function through the bus", async () => { + const { address, i2cBus, device } = await setup(); + + await device.deviceId(); + + // eslint-disable-next-line @typescript-eslint/unbound-method + expect(i2cBus.deviceId as jest.MockedFunction).toHaveBeenCalledTimes(1); + // eslint-disable-next-line @typescript-eslint/unbound-method + expect(i2cBus.deviceId as jest.MockedFunction).toHaveBeenCalledWith(address); + }); + }); - const spyOnWriteWord = jest.spyOn(bus, 'writeWord'); - await device.writeWord(1, 2); - expect(spyOnWriteWord).toHaveBeenCalledWith(address, 1, 2); + describe('static create', () => { + it('should create a Device instance', () => { + const bus = Bus.create({ busNumber: 1 }); + const device = Device.create({ bus, address: 0x7f }); - const spyOnWriteI2cBlock = jest.spyOn(bus, 'writeI2cBlock'); - await device.writeI2cBlock(1, 2, Buffer.from([])); - expect(spyOnWriteI2cBlock).toHaveBeenCalledWith(address, 1, 2, Buffer.from([])); + expect(device).toBeInstanceOf(Device); + expect(device).toHaveProperty('bus', bus); + expect(device.address).toBe(0x7f); + }); }); }); diff --git a/src/lib/Device.ts b/src/lib/Device.ts index c0513b9..2d7f7b7 100644 --- a/src/lib/Device.ts +++ b/src/lib/Device.ts @@ -1,46 +1,90 @@ -import BusInterface from './BusInterface'; -import DeviceInterface from './DeviceInterface'; - -const Device = ({ address, bus }: { address: number; bus: BusInterface }): DeviceInterface => ({ - get address() { - return address; - }, - get bus() { - return bus; - }, - i2cRead(length: number, buffer: Buffer) { - return bus.i2cRead(address, length, buffer); - }, - i2cWrite(length: number, buffer: Buffer) { - return bus.i2cWrite(address, length, buffer); - }, - - receiveByte() { - return bus.receiveByte(address); - }, - sendByte(byte: number) { - return bus.sendByte(address, byte); - }, - - readByte(command: number) { - return bus.readByte(address, command); - }, - readWord(command: number) { - return bus.readWord(address, command); - }, - readI2cBlock(command: number, length: number, buffer: Buffer) { - return bus.readI2cBlock(address, command, length, buffer); - }, - - writeByte(command: number, byte: number) { - return bus.writeByte(address, command, byte); - }, - writeWord(command: number, word: number) { - return bus.writeWord(address, command, word); - }, - writeI2cBlock(command: number, length: number, buffer: Buffer) { - return bus.writeI2cBlock(address, command, length, buffer); - }, -}); - -export default Device; +import { I2cReadResponse, I2cWriteResponse } from 'i2c-bus'; + +import Bus from './Bus'; + +export default class Device { + private bus!: Bus; + + readonly address: number; + + constructor({ bus, address }: { bus: Bus; address: number }) { + this.bus = bus; + this.address = address; + } + + async readByte(command: number): Promise { + const result = await this.bus.readByte(this.address, command); + + return result; + } + + async readWord(command: number): Promise { + const result = await this.bus.readWord(this.address, command); + + return result; + } + + async readI2cBlock(command: number, length: number, buffer: Buffer): Promise { + const result = await this.bus.readI2cBlock(this.address, command, length, buffer); + + return result; + } + + async receiveByte(): Promise { + const result = await this.bus.receiveByte(this.address); + + return result; + } + + async sendByte(byte: number): Promise { + await this.bus.sendByte(this.address, byte); + + return this; + } + + async writeByte(command: number, byte: number): Promise { + await this.bus.writeByte(this.address, command, byte); + + return this; + } + + async writeWord(command: number, word: number): Promise { + await this.bus.writeWord(this.address, command, word); + + return this; + } + + async writeQuick(bit: 0 | 1): Promise { + await this.bus.writeQuick(this.address, bit); + + return this; + } + + async writeI2cBlock(command: number, length: number, buffer: Buffer): Promise { + const result = await this.bus.writeI2cBlock(this.address, command, length, buffer); + + return result; + } + + async i2cRead(length: number, buffer: Buffer): Promise { + const result = await this.bus.i2cRead(this.address, length, buffer); + + return result; + } + + async i2cWrite(length: number, buffer: Buffer): Promise { + const result = await this.bus.i2cWrite(this.address, length, buffer); + + return result; + } + + async deviceId(): Promise { + const result = await this.bus.deviceId(this.address); + + return result; + } + + static create({ bus, address }: { bus: Bus; address: number }): Device { + return new Device({ bus, address }); + } +} diff --git a/src/lib/DeviceError.spec.ts b/src/lib/DeviceError.spec.ts deleted file mode 100644 index 2e0755c..0000000 --- a/src/lib/DeviceError.spec.ts +++ /dev/null @@ -1,11 +0,0 @@ -import DeviceError from './DeviceError'; - -describe('DeviceError', () => { - it('should instantiate error with bus number, address and message', () => { - const error = new DeviceError('Test error', 2, 0x55); - - expect(error.message).toBe('Test error'); - expect(error.busNumber).toBe(2); - expect(error.deviceAddress).toBe(0x55); - }); -}); diff --git a/src/lib/DeviceError.ts b/src/lib/DeviceError.ts deleted file mode 100644 index dda09a7..0000000 --- a/src/lib/DeviceError.ts +++ /dev/null @@ -1,15 +0,0 @@ -export default class DeviceError extends Error { - public busNumber: number; - public deviceAddress: number; - - constructor(message: string, busNumber: number, deviceAddress: number) { - super(message); - - this.name = this.constructor.name; - - Error.captureStackTrace(this, DeviceError); - - this.busNumber = busNumber; - this.deviceAddress = deviceAddress; - } -} diff --git a/src/lib/DeviceInterface.ts b/src/lib/DeviceInterface.ts deleted file mode 100644 index 0ca9bd2..0000000 --- a/src/lib/DeviceInterface.ts +++ /dev/null @@ -1,20 +0,0 @@ -import BusInterface from './BusInterface'; - -export default interface DeviceInterface { - readonly address: number; - readonly bus: BusInterface; - - i2cRead(length: number, buffer: Buffer): Promise; - i2cWrite(length: number, buffer: Buffer): Promise; - - receiveByte(): Promise; - sendByte(byte: number): Promise; - - readByte(command: number): Promise; - readI2cBlock(command: number, length: number, buffer: Buffer): Promise; - readWord(command: number): Promise; - - writeByte(command: number, byte: number): Promise; - writeWord(command: number, word: number): Promise; - writeI2cBlock(command: number, length: number, buffer: Buffer): Promise; -} diff --git a/src/lib/createI2cBusMock.ts b/src/lib/createI2cBusMock.ts deleted file mode 100644 index dad694a..0000000 --- a/src/lib/createI2cBusMock.ts +++ /dev/null @@ -1,124 +0,0 @@ -import { BufferCallback, CompletionCallback, I2cBus, I2cBusFuncs, open, ResultCallback } from 'i2c-bus'; - -const defaultI2cBusFuncs = { - i2c: false, - tenBitAddr: false, - protocolMangling: false, - smbusPec: false, - smbusBlockProcCall: false, - smbusQuick: false, - smbusReceiveByte: false, - smbusSendByte: false, - smbusReadByte: false, - smbusWriteByte: false, - smbusReadWord: false, - smbusWriteWord: false, - smbusProcCall: false, - smbusReadBlock: false, - smbusWriteBlock: false, - smbusReadI2cBlock: false, - smbusWriteI2cBlock: false, -}; - -// @TODO Add full features -const createI2cBusMock = ({ - devices = {}, - i2cBusFuncs = defaultI2cBusFuncs, -}: { - devices?: { [address: number]: Buffer }; - i2cBusFuncs?: I2cBusFuncs; -} = {}): typeof open => (_: number, openCallback: CompletionCallback): I2cBus => { - openCallback(null); - - return { - close(callback: CompletionCallback): void { - callback(null); - }, - closeSync() { - return; - }, - i2cFuncsSync() { - return i2cBusFuncs; - }, - i2cFuncs(callback: ResultCallback) { - callback(null, this.i2cFuncsSync()); - }, - scanSync() { - return Object.keys(devices).map(address => parseInt(address, 10)); - }, - scan(callback: ResultCallback) { - callback(null, this.scanSync()); - }, - i2cReadSync(address: number, length: number, buffer: Buffer) { - return devices[address].copy(buffer, 0, 0, length); - }, - i2cRead(address: number, length: number, buffer: Buffer, callback: BufferCallback) { - callback(null, this.i2cReadSync(address, length, buffer), buffer); - }, - i2cWriteSync(address: number, length: number, buffer: Buffer) { - return buffer.copy(devices[address], 0, 0, length); - }, - i2cWrite(address: number, length: number, buffer: Buffer, callback: BufferCallback) { - callback(null, this.i2cWriteSync(address, length, buffer), buffer); - }, - readByteSync(address: number, command: number) { - return devices[address][command]; - }, - readByte(address: number, command: number, callback: ResultCallback) { - callback(null, this.readByteSync(address, command)); - }, - readWordSync(address: number, command: number) { - return devices[address].readUInt16BE(command); - }, - readWord(address: number, command: number, callback: ResultCallback) { - return callback(null, this.readWordSync(address, command)); - }, - readI2cBlockSync(address: number, command: number, length: number, buffer: Buffer) { - return devices[address].copy(buffer, 0, command, command + length); - }, - readI2cBlock(address: number, command: number, length: number, buffer: Buffer, callback: BufferCallback) { - callback(null, this.readI2cBlockSync(address, command, length, buffer), buffer); - }, - receiveByteSync(address: number) { - return this.readByteSync(address, 0); - }, - receiveByte(address: number, callback: ResultCallback) { - callback(null, this.receiveByteSync(address)); - }, - writeByteSync(address: number, command: number, byte: number) { - devices[address][command] = byte; - }, - writeByte(address: number, command: number, byte: number, callback: CompletionCallback) { - this.writeByteSync(address, command, byte); - callback(null); - }, - sendByteSync(address: number, byte: number) { - this.writeByteSync(address, 0, byte); - }, - sendByte(address: number, byte: number, callback: CompletionCallback) { - this.sendByteSync(address, byte); - callback(null); - }, - writeWordSync(address: number, command: number, word: number) { - devices[address].writeUInt16BE(word, command); - }, - writeWord(address: number, command: number, word: number, callback: CompletionCallback) { - this.writeByteSync(address, command, word); - callback(null); - }, - writeQuickSync() { - return null; - }, - writeQuick(__: number, ___: number, ____: number, callback: CompletionCallback) { - callback(null); - }, - writeI2cBlockSync(address: number, command: number, length: number, buffer: Buffer) { - return buffer.copy(devices[address], command, 0, length); - }, - writeI2cBlock(address: number, command: number, length: number, buffer: Buffer, callback: BufferCallback) { - callback(null, this.writeI2cBlockSync(address, command, length, buffer), buffer); - }, - }; -}; - -export default createI2cBusMock; diff --git a/src/lib/types.ts b/src/lib/types.ts deleted file mode 100644 index cbf7317..0000000 --- a/src/lib/types.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { I2cBus, I2cBusFuncs } from 'i2c-bus'; - -/* tslint:disable-next-line:interface-name */ -export interface I2cBusPromised extends I2cBus { - closeAsync(): Promise; - - i2cFuncsAsync(): Promise; - scanAsync(): Promise; - - i2cReadAsync(address: number, length: number, buffer: Buffer): Promise; - i2cWriteAsync(address: number, length: number, buffer: Buffer): Promise; - - receiveByteAsync(address: number): Promise; - sendByteAsync(address: number, byte: number): Promise; - - readByteAsync(address: number, command: number): Promise; - readWordAsync(address: number, command: number): Promise; - readI2cBlockAsync(address: number, command: number, length: number, buffer: Buffer): Promise; - - writeByteAsync(address: number, command: number, byte: number): Promise; - writeWordAsync(address: number, command: number, word: number): Promise; - writeI2cBlockAsync(address: number, command: number, length: number, buffer: Buffer): Promise; -}