仕様に合わせる

This commit is contained in:
Nebel 2019-10-15 23:26:29 +09:00
parent 2e586e9be5
commit 90f36eb6f1
2 changed files with 57 additions and 10 deletions

View file

@ -2,10 +2,12 @@
Object.defineProperty(exports, "__esModule", { value: true }); Object.defineProperty(exports, "__esModule", { value: true });
const events_1 = require("events"); const events_1 = require("events");
const fs_1 = require("fs"); const fs_1 = require("fs");
const path = require("path");
/** /**
* Interval of file system polling, in milliseconds. * Interval of file system polling, in milliseconds.
*/ */
const PollingInterval = 100; const PollingInterval = 100;
const SysfsGPIOPath = "/sys/class/gpio";
const Uint16Max = 65535; const Uint16Max = 65535;
function parseUint16(string) { function parseUint16(string) {
const n = Number.parseInt(string, 10); const n = Number.parseInt(string, 10);
@ -78,10 +80,19 @@ class GPIOPort extends events_1.EventEmitter {
if (!/^(in|out)$/.test(direction)) { if (!/^(in|out)$/.test(direction)) {
throw new InvalidAccessError(`Must be "in" or "out".`); throw new InvalidAccessError(`Must be "in" or "out".`);
} }
try {
await fs_1.promises.access(path.join(SysfsGPIOPath, `gpio${this.portNumber}`));
this._exported = true;
}
catch {
this._exported = false;
}
try { try {
clearInterval(this._timeout); clearInterval(this._timeout);
await fs_1.promises.writeFile(`/sys/class/gpio/export`, String(this.portNumber)); if (!this.exported) {
await fs_1.promises.writeFile(`/sys/class/gpio/gpio${this.portNumber}/direction`, direction); await fs_1.promises.writeFile(path.join(SysfsGPIOPath, "export"), String(this.portNumber));
}
await fs_1.promises.writeFile(path.join(SysfsGPIOPath, `gpio${this.portNumber}`, "direction"), direction);
if (direction === "in") { if (direction === "in") {
this._timeout = setInterval(this.read.bind(this), this._pollingInterval); this._timeout = setInterval(this.read.bind(this), this._pollingInterval);
} }
@ -95,7 +106,7 @@ class GPIOPort extends events_1.EventEmitter {
async unexport() { async unexport() {
clearInterval(this._timeout); clearInterval(this._timeout);
try { try {
await fs_1.promises.writeFile(`/sys/class/gpio/unexport`, String(this.portNumber)); await fs_1.promises.writeFile(path.join(SysfsGPIOPath, "unexport"), String(this.portNumber));
} }
catch (error) { catch (error) {
throw new OperationError(error); throw new OperationError(error);
@ -103,8 +114,11 @@ class GPIOPort extends events_1.EventEmitter {
this._exported = false; this._exported = false;
} }
async read() { async read() {
if (!(this.exported && this.direction === "in")) {
throw new InvalidAccessError(`The exported must be true and value of direction must be "in".`);
}
try { try {
const buffer = await fs_1.promises.readFile(`/sys/class/gpio/gpio${this.portNumber}/value`); const buffer = await fs_1.promises.readFile(path.join(SysfsGPIOPath, `gpio${this.portNumber}`, "value"));
const value = parseUint16(buffer.toString()); const value = parseUint16(buffer.toString());
if (this._value !== value) { if (this._value !== value) {
this._value = value; this._value = value;
@ -117,8 +131,11 @@ class GPIOPort extends events_1.EventEmitter {
} }
} }
async write(value) { 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 { try {
await fs_1.promises.writeFile(`/sys/class/gpio/gpio${this.portNumber}/value`, parseUint16(value.toString()).toString()); await fs_1.promises.writeFile(path.join(SysfsGPIOPath, `gpio${this.portNumber}`, "value"), parseUint16(value.toString()).toString());
} }
catch (error) { catch (error) {
throw new OperationError(error); throw new OperationError(error);

View file

@ -1,11 +1,14 @@
import { EventEmitter } from "events"; import { EventEmitter } from "events";
import { promises as fs } from "fs"; import { promises as fs } from "fs";
import * as path from "path";
/** /**
* Interval of file system polling, in milliseconds. * Interval of file system polling, in milliseconds.
*/ */
const PollingInterval = 100; const PollingInterval = 100;
const SysfsGPIOPath = "/sys/class/gpio";
const Uint16Max = 65535; const Uint16Max = 65535;
function parseUint16(string: string) { function parseUint16(string: string) {
@ -127,11 +130,23 @@ export class GPIOPort extends EventEmitter {
throw new InvalidAccessError(`Must be "in" or "out".`); throw new InvalidAccessError(`Must be "in" or "out".`);
} }
try {
await fs.access(path.join(SysfsGPIOPath, `gpio${this.portNumber}`));
this._exported = true;
} catch {
this._exported = false;
}
try { try {
clearInterval(this._timeout as any); clearInterval(this._timeout as any);
await fs.writeFile(`/sys/class/gpio/export`, String(this.portNumber)); if (!this.exported) {
await fs.writeFile(
path.join(SysfsGPIOPath, "export"),
String(this.portNumber)
);
}
await fs.writeFile( await fs.writeFile(
`/sys/class/gpio/gpio${this.portNumber}/direction`, path.join(SysfsGPIOPath, `gpio${this.portNumber}`, "direction"),
direction direction
); );
if (direction === "in") { if (direction === "in") {
@ -152,7 +167,10 @@ export class GPIOPort extends EventEmitter {
clearInterval(this._timeout as any); clearInterval(this._timeout as any);
try { try {
await fs.writeFile(`/sys/class/gpio/unexport`, String(this.portNumber)); await fs.writeFile(
path.join(SysfsGPIOPath, "unexport"),
String(this.portNumber)
);
} catch (error) { } catch (error) {
throw new OperationError(error); throw new OperationError(error);
} }
@ -161,9 +179,15 @@ export class GPIOPort extends EventEmitter {
} }
async read() { async read() {
if (!(this.exported && this.direction === "in")) {
throw new InvalidAccessError(
`The exported must be true and value of direction must be "in".`
);
}
try { try {
const buffer = await fs.readFile( const buffer = await fs.readFile(
`/sys/class/gpio/gpio${this.portNumber}/value` path.join(SysfsGPIOPath, `gpio${this.portNumber}`, "value")
); );
const value = parseUint16(buffer.toString()) as GPIOValue; const value = parseUint16(buffer.toString()) as GPIOValue;
@ -180,9 +204,15 @@ export class GPIOPort extends EventEmitter {
} }
async write(value: GPIOValue) { async write(value: GPIOValue) {
if (!(this.exported && this.direction === "out")) {
throw new InvalidAccessError(
`The exported must be true and value of direction must be "out".`
);
}
try { try {
await fs.writeFile( await fs.writeFile(
`/sys/class/gpio/gpio${this.portNumber}/value`, path.join(SysfsGPIOPath, `gpio${this.portNumber}`, "value"),
parseUint16(value.toString()).toString() parseUint16(value.toString()).toString()
); );
} catch (error) { } catch (error) {