initial commit

This commit is contained in:
Nebel 2019-10-18 03:23:29 +09:00
commit 3c030c7530
8 changed files with 295 additions and 0 deletions

1
.gitignore vendored Normal file
View file

@ -0,0 +1 @@
/node_modules/

26
README.md Normal file
View file

@ -0,0 +1,26 @@
# @notweb/i2c
I2C access with Node.js
## Usage
```js
const { requestI2CAccess } = require("@notweb/i2c");
const ADT7410_ADDR = 0x48;
async function main() {
const i2cAccess = await requestI2CAccess();
const port = gpioAccess.ports.get(1);
const i2cSlave = await port.open(ADT7410_ADDR);
const temperature =
(((await i2cSlave.read8(0x00)) << 8) + (await i2cSlave.read8(0x01))) / 128;
console.log(`Temperature: ${temperature} ℃`);
}
main();
```
## Document
[Web I2C API](http://browserobo.github.io/WebI2C)

32
index.d.ts vendored Normal file
View file

@ -0,0 +1,32 @@
declare type PortNumber = number;
declare type PortName = string;
declare type I2CSlaveAddress = number;
export declare class I2CAccess {
private readonly _ports;
constructor(ports?: I2CPortMap);
readonly ports: I2CPortMap;
}
/**
* Different from Web GPIO API specification.
*/
export declare class I2CPortMap extends Map<PortNumber, I2CPort> {
getByName(portName: PortName): I2CPort | undefined;
}
export declare class I2CPort {
private readonly _portNumber;
constructor(portNumber: PortNumber);
readonly portNumber: number;
readonly portName: string;
open(slaveAddress: I2CSlaveAddress): Promise<I2CSlaveDevice>;
}
export interface I2CSlaveDevice {
readonly slaveAddress: I2CSlaveAddress;
read8(registerNumber: number): Promise<number>;
read16(registerNumber: number): Promise<number>;
write8(registerNumber: number, value: number): Promise<number>;
write16(registerNumber: number, value: number): Promise<number>;
}
export declare class OperationError extends Error {
}
export declare function requestI2CAccess(): Promise<I2CAccess>;
export {};

66
index.js Normal file
View file

@ -0,0 +1,66 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const i2c_bus_1 = require("i2c-bus");
const I2CPortMapSizeMax = 32;
const Uint16Max = 65535;
function parseUint16(string) {
const n = Number.parseInt(string, 10);
if (0 <= n && n <= Uint16Max)
return n;
else
throw new RangeError(`Must be between 0 and ${Uint16Max}.`);
}
class I2CAccess {
constructor(ports) {
this._ports = ports == null ? new I2CPortMap() : ports;
}
get ports() {
return this._ports;
}
}
exports.I2CAccess = I2CAccess;
/**
* Different from Web GPIO API specification.
*/
class I2CPortMap extends Map {
getByName(portName) {
const matches = /^i2c-(\d+)$/.exec(portName);
return matches == null ? undefined : this.get(parseUint16(matches[1]));
}
}
exports.I2CPortMap = I2CPortMap;
class I2CPort {
constructor(portNumber) {
this._portNumber = parseUint16(portNumber.toString());
}
get portNumber() {
return this._portNumber;
}
get portName() {
return `i2c-${this.portNumber}`;
}
async open(slaveAddress) {
const bus = await i2c_bus_1.openPromisified(this.portNumber).catch(error => {
throw new OperationError(error);
});
return {
slaveAddress,
read8: cmd => bus.readByte(slaveAddress, cmd),
read16: cmd => bus.readWord(slaveAddress, cmd),
write8: (cmd, byte) => bus.writeByte(slaveAddress, cmd, byte),
write16: (cmd, word) => bus.writeWord(slaveAddress, cmd, word)
};
}
}
exports.I2CPort = I2CPort;
class OperationError extends Error {
}
exports.OperationError = OperationError;
async function requestI2CAccess() {
const ports = new I2CPortMap([...Array(I2CPortMapSizeMax).keys()].map(portNumber => [
portNumber,
new I2CPort(portNumber)
]));
return new I2CAccess(ports);
}
exports.requestI2CAccess = requestI2CAccess;

90
index.ts Normal file
View file

@ -0,0 +1,90 @@
import { openPromisified } from "i2c-bus";
const I2CPortMapSizeMax = 32;
const Uint16Max = 65535;
function parseUint16(string: string) {
const n = Number.parseInt(string, 10);
if (0 <= n && n <= Uint16Max) return n;
else throw new RangeError(`Must be between 0 and ${Uint16Max}.`);
}
type PortNumber = number;
type PortName = string;
type I2CSlaveAddress = number;
export class I2CAccess {
private readonly _ports: I2CPortMap;
constructor(ports?: I2CPortMap) {
this._ports = ports == null ? new I2CPortMap() : ports;
}
get ports() {
return this._ports;
}
}
/**
* Different from Web GPIO API specification.
*/
export class I2CPortMap extends Map<PortNumber, I2CPort> {
getByName(portName: PortName) {
const matches = /^i2c-(\d+)$/.exec(portName);
return matches == null ? undefined : this.get(parseUint16(matches[1]));
}
}
export class I2CPort {
private readonly _portNumber: PortNumber;
constructor(portNumber: PortNumber) {
this._portNumber = parseUint16(portNumber.toString());
}
get portNumber() {
return this._portNumber;
}
get portName() {
return `i2c-${this.portNumber}`;
}
async open(slaveAddress: I2CSlaveAddress): Promise<I2CSlaveDevice> {
const bus = await openPromisified(this.portNumber).catch(error => {
throw new OperationError(error);
});
return {
slaveAddress,
read8: cmd => bus.readByte(slaveAddress, cmd),
read16: cmd => bus.readWord(slaveAddress, cmd),
write8: (cmd, byte) => bus.writeByte(slaveAddress, cmd, byte),
write16: (cmd, word) => bus.writeWord(slaveAddress, cmd, word)
};
}
}
export interface I2CSlaveDevice {
readonly slaveAddress: I2CSlaveAddress;
read8(registerNumber: number): Promise<number>;
read16(registerNumber: number): Promise<number>;
write8(registerNumber: number, value: number): Promise<number>;
write16(registerNumber: number, value: number): Promise<number>;
}
export class OperationError extends Error {}
export async function requestI2CAccess(): Promise<I2CAccess> {
const ports = new I2CPortMap(
[...Array(I2CPortMapSizeMax).keys()].map(portNumber => [
portNumber,
new I2CPort(portNumber)
])
);
return new I2CAccess(ports);
}

25
package.json Normal file
View file

@ -0,0 +1,25 @@
{
"name": "@notweb/i2c",
"version": "0.0.1",
"description": "I2C access with Node.js",
"main": "index.js",
"repository": {
"type": "git",
"url": "https://github.com/kou029w/notweb-i2c.git"
},
"author": "Kohei Watanabe <kou029w@gmail.com>",
"license": "MIT",
"publishConfig": {
"access": "public"
},
"dependencies": {
"i2c-bus": "^5.1.0"
},
"devDependencies": {
"@types/node": "^12.7.12",
"typescript": "^3.6.4"
},
"scripts": {
"build": "tsc"
}
}

17
tsconfig.json Normal file
View file

@ -0,0 +1,17 @@
{
"compilerOptions": {
"target": "esnext",
"module": "commonjs",
"moduleResolution": "node",
"declaration": true,
"noImplicitThis": true,
"alwaysStrict": true,
"strictBindCallApply": true,
"strictNullChecks": true,
"strictFunctionTypes": true,
"strictPropertyInitialization": true,
"noImplicitReturns": true,
"noUnusedLocals": true,
"noUnusedParameters": true
}
}

38
yarn.lock Normal file
View file

@ -0,0 +1,38 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1
"@types/node@^12.7.12":
version "12.7.12"
resolved "https://registry.yarnpkg.com/@types/node/-/node-12.7.12.tgz#7c6c571cc2f3f3ac4a59a5f2bd48f5bdbc8653cc"
integrity sha512-KPYGmfD0/b1eXurQ59fXD1GBzhSQfz6/lKBxkaHX9dKTzjXbK68Zt7yGUxUsCS1jeTy/8aL+d9JEr+S54mpkWQ==
bindings@^1.5.0:
version "1.5.0"
resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df"
integrity sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==
dependencies:
file-uri-to-path "1.0.0"
file-uri-to-path@1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd"
integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==
i2c-bus@^5.1.0:
version "5.1.0"
resolved "https://registry.yarnpkg.com/i2c-bus/-/i2c-bus-5.1.0.tgz#7d667d225c09017cf044f75fc593d5ea3e0f4ea6"
integrity sha512-u/q1fuZ5xrG77y3uo1rAANycboXsRNjneN+6jXRNMT2yRNpanVkbAP+IArwgsPRCHaY/zKxw7x5G8Y2fSPNseA==
dependencies:
bindings "^1.5.0"
nan "^2.14.0"
nan@^2.14.0:
version "2.14.0"
resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.0.tgz#7818f722027b2459a86f0295d434d1fc2336c52c"
integrity sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==
typescript@^3.6.4:
version "3.6.4"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.6.4.tgz#b18752bb3792bc1a0281335f7f6ebf1bbfc5b91d"
integrity sha512-unoCll1+l+YK4i4F8f22TaNVPRHcD9PA3yCuZ8g5e0qGqlVlJ/8FSateOLLSagn+Yg5+ZwuPkL8LFUc0Jcvksg==