mirror of
https://github.com/chirimen-oh/node-web-gpio.git
synced 2025-01-18 16:08:00 +00:00
build/publishプロセスの整理
This commit is contained in:
parent
5ba8998425
commit
7b91907d20
5 changed files with 9 additions and 227 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1 +1,2 @@
|
||||||
|
/dist/
|
||||||
/node_modules/
|
/node_modules/
|
||||||
|
|
56
index.d.ts
vendored
56
index.d.ts
vendored
|
@ -1,56 +0,0 @@
|
||||||
/// <reference types="node" />
|
|
||||||
import { EventEmitter } from "events";
|
|
||||||
declare type PortNumber = number;
|
|
||||||
declare type PortName = string;
|
|
||||||
declare type PinName = string;
|
|
||||||
declare type DirectionMode = "in" | "out";
|
|
||||||
declare type GPIOValue = 0 | 1;
|
|
||||||
interface GPIOChangeEvent {
|
|
||||||
readonly value: GPIOValue;
|
|
||||||
readonly port: GPIOPort;
|
|
||||||
}
|
|
||||||
interface GPIOChangeEventHandler {
|
|
||||||
(event: GPIOChangeEvent): void;
|
|
||||||
}
|
|
||||||
export declare class GPIOAccess extends EventEmitter {
|
|
||||||
private readonly _ports;
|
|
||||||
onchange: GPIOChangeEventHandler | undefined;
|
|
||||||
constructor(ports?: GPIOPortMap);
|
|
||||||
get ports(): GPIOPortMap;
|
|
||||||
/**
|
|
||||||
* Unexport all exported GPIO ports.
|
|
||||||
*/
|
|
||||||
unexportAll(): Promise<void>;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Different from Web GPIO API specification.
|
|
||||||
*/
|
|
||||||
export declare class GPIOPortMap extends Map<PortNumber, GPIOPort> {
|
|
||||||
}
|
|
||||||
export declare class GPIOPort extends EventEmitter {
|
|
||||||
private readonly _portNumber;
|
|
||||||
private readonly _pollingInterval;
|
|
||||||
private _direction;
|
|
||||||
private _exported;
|
|
||||||
private _value;
|
|
||||||
private _timeout;
|
|
||||||
onchange: GPIOChangeEventHandler | undefined;
|
|
||||||
constructor(portNumber: PortNumber);
|
|
||||||
get portNumber(): PortNumber;
|
|
||||||
get portName(): PortName;
|
|
||||||
get pinName(): PinName;
|
|
||||||
get direction(): DirectionMode;
|
|
||||||
get exported(): boolean;
|
|
||||||
export(direction: DirectionMode): Promise<void>;
|
|
||||||
unexport(): Promise<void>;
|
|
||||||
read(): Promise<GPIOValue>;
|
|
||||||
write(value: GPIOValue): Promise<void>;
|
|
||||||
}
|
|
||||||
export declare class InvalidAccessError extends Error {
|
|
||||||
constructor(message: string);
|
|
||||||
}
|
|
||||||
export declare class OperationError extends Error {
|
|
||||||
constructor(message: string);
|
|
||||||
}
|
|
||||||
export declare function requestGPIOAccess(): Promise<GPIOAccess>;
|
|
||||||
export {};
|
|
169
index.js
169
index.js
|
@ -1,169 +0,0 @@
|
||||||
"use strict";
|
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
|
||||||
const events_1 = require("events");
|
|
||||||
const fs_1 = require("fs");
|
|
||||||
const path = require("path");
|
|
||||||
/**
|
|
||||||
* Interval of file system polling, in milliseconds.
|
|
||||||
*/
|
|
||||||
const PollingInterval = 100;
|
|
||||||
const SysfsGPIOPath = "/sys/class/gpio";
|
|
||||||
const GPIOPortMapSizeMax = 1024;
|
|
||||||
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 GPIOAccess extends events_1.EventEmitter {
|
|
||||||
constructor(ports) {
|
|
||||||
super();
|
|
||||||
this._ports = ports == null ? new GPIOPortMap() : ports;
|
|
||||||
this._ports.forEach(port => port.on("change", event => {
|
|
||||||
this.emit("change", event);
|
|
||||||
}));
|
|
||||||
this.on("change", (event) => {
|
|
||||||
if (this.onchange !== undefined)
|
|
||||||
this.onchange(event);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
get ports() {
|
|
||||||
return this._ports;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Unexport all exported GPIO ports.
|
|
||||||
*/
|
|
||||||
async unexportAll() {
|
|
||||||
await Promise.all([...this.ports.values()].map(port => port.exported ? port.unexport() : undefined));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
exports.GPIOAccess = GPIOAccess;
|
|
||||||
/**
|
|
||||||
* Different from Web GPIO API specification.
|
|
||||||
*/
|
|
||||||
class GPIOPortMap extends Map {
|
|
||||||
}
|
|
||||||
exports.GPIOPortMap = GPIOPortMap;
|
|
||||||
class GPIOPort extends events_1.EventEmitter {
|
|
||||||
constructor(portNumber) {
|
|
||||||
super();
|
|
||||||
this._portNumber = parseUint16(portNumber.toString());
|
|
||||||
this._pollingInterval = PollingInterval;
|
|
||||||
this._direction = new OperationError("Unknown direction.");
|
|
||||||
this._exported = new OperationError("Unknown export.");
|
|
||||||
this.on("change", (event) => {
|
|
||||||
if (this.onchange !== undefined)
|
|
||||||
this.onchange(event);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
get portNumber() {
|
|
||||||
return this._portNumber;
|
|
||||||
}
|
|
||||||
get portName() {
|
|
||||||
return `gpio${this.portNumber}`;
|
|
||||||
}
|
|
||||||
get pinName() {
|
|
||||||
// NOTE: Unknown pinName.
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
get direction() {
|
|
||||||
if (this._direction instanceof OperationError)
|
|
||||||
throw this._direction;
|
|
||||||
return this._direction;
|
|
||||||
}
|
|
||||||
get exported() {
|
|
||||||
if (this._exported instanceof OperationError)
|
|
||||||
throw this._exported;
|
|
||||||
return this._exported;
|
|
||||||
}
|
|
||||||
async export(direction) {
|
|
||||||
if (!/^(in|out)$/.test(direction)) {
|
|
||||||
throw new InvalidAccessError(`Must be "in" or "out".`);
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
await fs_1.promises.access(path.join(SysfsGPIOPath, this.portName));
|
|
||||||
this._exported = true;
|
|
||||||
}
|
|
||||||
catch {
|
|
||||||
this._exported = false;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
clearInterval(this._timeout);
|
|
||||||
if (!this.exported) {
|
|
||||||
await fs_1.promises.writeFile(path.join(SysfsGPIOPath, "export"), String(this.portNumber));
|
|
||||||
}
|
|
||||||
await fs_1.promises.writeFile(path.join(SysfsGPIOPath, this.portName, "direction"), direction);
|
|
||||||
if (direction === "in") {
|
|
||||||
this._timeout = setInterval(this.read.bind(this), this._pollingInterval);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (error) {
|
|
||||||
throw new OperationError(error);
|
|
||||||
}
|
|
||||||
this._direction = direction;
|
|
||||||
this._exported = true;
|
|
||||||
}
|
|
||||||
async unexport() {
|
|
||||||
clearInterval(this._timeout);
|
|
||||||
try {
|
|
||||||
await fs_1.promises.writeFile(path.join(SysfsGPIOPath, "unexport"), String(this.portNumber));
|
|
||||||
}
|
|
||||||
catch (error) {
|
|
||||||
throw new OperationError(error);
|
|
||||||
}
|
|
||||||
this._exported = false;
|
|
||||||
}
|
|
||||||
async read() {
|
|
||||||
if (!(this.exported && this.direction === "in")) {
|
|
||||||
throw new InvalidAccessError(`The exported must be true and value of direction must be "in".`);
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
const buffer = await fs_1.promises.readFile(path.join(SysfsGPIOPath, this.portName, "value"));
|
|
||||||
const value = parseUint16(buffer.toString());
|
|
||||||
if (this._value !== value) {
|
|
||||||
this._value = value;
|
|
||||||
this.emit("change", { value, port: this });
|
|
||||||
}
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
catch (error) {
|
|
||||||
throw new OperationError(error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
async write(value) {
|
|
||||||
if (!(this.exported && this.direction === "out")) {
|
|
||||||
throw new InvalidAccessError(`The exported must be true and value of direction must be "out".`);
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
await fs_1.promises.writeFile(path.join(SysfsGPIOPath, this.portName, "value"), parseUint16(value.toString()).toString());
|
|
||||||
}
|
|
||||||
catch (error) {
|
|
||||||
throw new OperationError(error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
exports.GPIOPort = GPIOPort;
|
|
||||||
class InvalidAccessError extends Error {
|
|
||||||
constructor(message) {
|
|
||||||
super(message);
|
|
||||||
this.name = this.constructor.name;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
exports.InvalidAccessError = InvalidAccessError;
|
|
||||||
class OperationError extends Error {
|
|
||||||
constructor(message) {
|
|
||||||
super(message);
|
|
||||||
this.name = this.constructor.name;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
exports.OperationError = OperationError;
|
|
||||||
async function requestGPIOAccess() {
|
|
||||||
const ports = new GPIOPortMap([...Array(GPIOPortMapSizeMax).keys()].map(portNumber => [
|
|
||||||
portNumber,
|
|
||||||
new GPIOPort(portNumber)
|
|
||||||
]));
|
|
||||||
return new GPIOAccess(ports);
|
|
||||||
}
|
|
||||||
exports.requestGPIOAccess = requestGPIOAccess;
|
|
|
@ -2,7 +2,11 @@
|
||||||
"name": "node-web-gpio",
|
"name": "node-web-gpio",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"description": "GPIO access with Node.js",
|
"description": "GPIO access with Node.js",
|
||||||
"main": "index.js",
|
"main": "dist/index.js",
|
||||||
|
"types": "dist/index.d.ts",
|
||||||
|
"files": [
|
||||||
|
"dist/*"
|
||||||
|
],
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/chirimen-oh/node-web-gpio.git"
|
"url": "https://github.com/chirimen-oh/node-web-gpio.git"
|
||||||
|
@ -14,7 +18,8 @@
|
||||||
"typescript": "^4.0.2"
|
"typescript": "^4.0.2"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "tsc"
|
"build": "tsc",
|
||||||
|
"prepublish": "rm -rf dist && yarn build"
|
||||||
},
|
},
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"gpio",
|
"gpio",
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
|
"outDir": "dist",
|
||||||
"target": "esnext",
|
"target": "esnext",
|
||||||
"module": "commonjs",
|
"module": "commonjs",
|
||||||
"moduleResolution": "node",
|
"moduleResolution": "node",
|
||||||
|
|
Loading…
Add table
Reference in a new issue