diff --git a/package.json b/package.json index 5fe9139..d33e5f0 100644 --- a/package.json +++ b/package.json @@ -42,7 +42,11 @@ } }, "dependencies": { + "@types/bluebird": "^3.5.24", + "@types/i2c-bus": "^1.0.19", "@types/node": "^10.12.12", + "bluebird": "^3.5.3", + "i2c-bus": "^4.0.6", "typescript": "^3.2.2" } } diff --git a/src/Bus/Bus.ts b/src/Bus/Bus.ts new file mode 100644 index 0000000..6c8b5ea --- /dev/null +++ b/src/Bus/Bus.ts @@ -0,0 +1,164 @@ +import { promisifyAll } from 'bluebird'; +import { I2cBusFuncs, open as openI2cBusFn } from 'i2c-bus'; + +import { I2cBusPromised } from '../types'; + +import BusError from './BusError'; + +export 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; +} + +export default ({ busNumber = 1, openI2cBus = openI2cBusFn } = {}): 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(openI2cBus(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('BusInterface is not open', busNumber); + } + + await i2cBus.closeAsync(); + + isOpen = false; + i2cBus = null; + + return this; + }, + + async i2cFuncs() { + if (!i2cBus || !isOpen) { + throw new BusError('BusInterface is not open', busNumber); + } + + return i2cBus.i2cFuncsAsync(); + }, + async scan() { + if (!i2cBus || !isOpen) { + throw new BusError('BusInterface is not open', busNumber); + } + + return i2cBus.scanAsync(); + }, + + async i2cRead(address: number, length: number, buffer: Buffer) { + if (!i2cBus || !isOpen) { + throw new BusError('BusInterface is not open', busNumber); + } + + return i2cBus.i2cReadAsync(address, length, buffer); + }, + async i2cWrite(address: number, length: number, buffer: Buffer) { + if (!i2cBus || !isOpen) { + throw new BusError('BusInterface is not open', busNumber); + } + + return i2cBus.i2cWriteAsync(address, length, buffer); + }, + + async receiveByte(address: number) { + if (!i2cBus || !isOpen) { + throw new BusError('BusInterface is not open', busNumber); + } + + return i2cBus.receiveByteAsync(address); + }, + async sendByte(address: number, byte: number) { + if (!i2cBus || !isOpen) { + throw new BusError('BusInterface is not open', busNumber); + } + + return i2cBus.sendByteAsync(address, byte); + }, + + async readByte(address: number, command: number) { + if (!i2cBus || !isOpen) { + throw new BusError('BusInterface is not open', busNumber); + } + + return i2cBus.readByteAsync(address, command); + }, + async readWord(address: number, command: number) { + if (!i2cBus || !isOpen) { + throw new BusError('BusInterface is not open', busNumber); + } + + return i2cBus.readWordAsync(address, command); + }, + async readI2cBlock(address: number, command: number, length: number, buffer: Buffer) { + if (!i2cBus || !isOpen) { + throw new BusError('BusInterface is not open', busNumber); + } + + return i2cBus.readI2cBlockAsync(address, command, length, buffer); + }, + + async writeByte(address: number, command: number, byte: number) { + if (!i2cBus || !isOpen) { + throw new BusError('BusInterface is not open', busNumber); + } + + return i2cBus.writeByteAsync(address, command, byte); + }, + async writeWord(address: number, command: number, word: number) { + if (!i2cBus || !isOpen) { + throw new BusError('BusInterface is not open', busNumber); + } + + return i2cBus.writeWordAsync(address, command, word); + }, + async writeI2cBlock(address: number, command: number, length: number, buffer: Buffer) { + if (!i2cBus || !isOpen) { + throw new BusError('BusInterface is not open', busNumber); + } + + return i2cBus.writeI2cBlockAsync(address, command, length, buffer); + }, + }; +}; diff --git a/src/Bus/BusError.ts b/src/Bus/BusError.ts new file mode 100644 index 0000000..78c7a37 --- /dev/null +++ b/src/Bus/BusError.ts @@ -0,0 +1,13 @@ +export default class BusError extends Error { + public busNumber: number; + + constructor(msg: string, busNumber: number) { + super(msg); + + if (Error.captureStackTrace) { + Error.captureStackTrace(this, BusError); + } + + this.busNumber = busNumber; + } +} diff --git a/src/Bus/index.ts b/src/Bus/index.ts new file mode 100644 index 0000000..42cc7d3 --- /dev/null +++ b/src/Bus/index.ts @@ -0,0 +1,4 @@ +import Bus, { BusInterface } from './Bus'; +import BusError from './BusError'; + +export { Bus, BusError, BusInterface }; diff --git a/src/index.ts b/src/index.ts new file mode 100644 index 0000000..741bb8b --- /dev/null +++ b/src/index.ts @@ -0,0 +1,3 @@ +import { Bus, BusError, BusInterface } from './Bus'; + +export { Bus, BusError, BusInterface }; diff --git a/yarn.lock b/yarn.lock index 08004e9..5d8e033 100644 --- a/yarn.lock +++ b/yarn.lock @@ -139,12 +139,24 @@ into-stream "^4.0.0" lodash "^4.17.4" +"@types/bluebird@^3.5.24": + version "3.5.24" + resolved "https://registry.yarnpkg.com/@types/bluebird/-/bluebird-3.5.24.tgz#11f76812531c14f793b8ecbf1de96f672905de8a" + integrity sha512-YeQoDpq4Lm8ppSBqAnAeF/xy1cYp/dMTif2JFcvmAbETMRlvKHT2iLcWu+WyYiJO3b3Ivokwo7EQca/xfLVJmg== + +"@types/i2c-bus@^1.0.19": + version "1.0.19" + resolved "https://registry.yarnpkg.com/@types/i2c-bus/-/i2c-bus-1.0.19.tgz#58a9208370abf4d8e910ae37b4aa4cfbaecbc7d4" + integrity sha512-kdzu2dQz6rEdPVNzyHFxtmr78p1+X2RG4JZo7OTTdb9i122CGhSf8oNoR+aMcKW+0UhTOnCaNRbBWFh6h1aEag== + dependencies: + "@types/node" "*" + "@types/jest@^23.3.10": version "23.3.10" resolved "https://registry.yarnpkg.com/@types/jest/-/jest-23.3.10.tgz#4897974cc317bf99d4fe6af1efa15957fa9c94de" integrity sha512-DC8xTuW/6TYgvEg3HEXS7cu9OijFqprVDXXiOcdOKZCU/5PJNLZU37VVvmZHdtMiGOa8wAA/We+JzbdxFzQTRQ== -"@types/node@^10.12.12": +"@types/node@*", "@types/node@^10.12.12": version "10.12.12" resolved "https://registry.yarnpkg.com/@types/node/-/node-10.12.12.tgz#e15a9d034d9210f00320ef718a50c4a799417c47" integrity sha512-Pr+6JRiKkfsFvmU/LK68oBRCQeEg36TyAbPhc2xpez24OOZZCuoIhWGTd39VZy6nGafSbxzGouFPTFD/rR1A0A== @@ -661,6 +673,11 @@ bin-links@^1.1.2: graceful-fs "^4.1.11" write-file-atomic "^2.3.0" +bindings@^1.3.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.3.1.tgz#21fc7c6d67c18516ec5aaa2815b145ff77b26ea5" + integrity sha512-i47mqjF9UbjxJhxGf+pZ6kSxrnI3wBLlnGI2ArWJ4r0VrvDS7ZYXkprq/pLaBWYq4GM0r4zdHY+NNRqEMU7uew== + block-stream@*: version "0.0.9" resolved "https://registry.yarnpkg.com/block-stream/-/block-stream-0.0.9.tgz#13ebfe778a03205cfe03751481ebb4b3300c126a" @@ -668,7 +685,7 @@ block-stream@*: dependencies: inherits "~2.0.0" -bluebird@^3.5.0, bluebird@^3.5.1, bluebird@~3.5.1: +bluebird@^3.5.0, bluebird@^3.5.1, bluebird@^3.5.3, bluebird@~3.5.1: version "3.5.3" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.3.tgz#7d01c6f9616c9a51ab0f8c549a79dfe6ec33efa7" integrity sha512-/qKPUQlaW1OyR51WeCPBvRnAlnZFUJkCSG5HzGnuIqhgyJtF+T94lFnn33eiazjRm2LAHVy2guNnaq48X9SJuw== @@ -2342,6 +2359,14 @@ humanize-ms@^1.2.1: dependencies: ms "^2.0.0" +i2c-bus@^4.0.6: + version "4.0.6" + resolved "https://registry.yarnpkg.com/i2c-bus/-/i2c-bus-4.0.6.tgz#5a3114a06c66fc1c91afb93a972df6c4815e5311" + integrity sha512-9I/JxojEPnFvEdw3whDQlgQ35NHOGCt0mADfImQVhDz5elhMQm26qhR+XnWVHtt3zIf9B9Wun4x8pMaeuGxlKQ== + dependencies: + bindings "^1.3.0" + nan "^2.11.1" + iconv-lite@0.4.24, iconv-lite@^0.4.4, iconv-lite@~0.4.13: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" @@ -3976,7 +4001,7 @@ mute-stream@~0.0.4: resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" integrity sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s= -nan@^2.9.2: +nan@^2.11.1, nan@^2.9.2: version "2.11.1" resolved "https://registry.yarnpkg.com/nan/-/nan-2.11.1.tgz#90e22bccb8ca57ea4cd37cc83d3819b52eea6766" integrity sha512-iji6k87OSXa0CcrLl9z+ZiYSuR2o+c0bGuNmXdrhTQTakxytAFsC56SArGYoiHlJlFoHSnvmhpceZJaXkVuOtA==