129 lines
3.2 KiB
TypeScript
129 lines
3.2 KiB
TypeScript
import * as fs from "fs";
|
|
|
|
export class GPIO {
|
|
|
|
private static openPorts: GPIO[] = [];
|
|
private readonly gpioPath: string;
|
|
private readonly gpioPin: number;
|
|
|
|
public constructor(pin: number, direction: 'in' | 'out') {
|
|
const gpioPath = `/sys/class/gpio/gpio${pin}`;
|
|
this.gpioPath = gpioPath;
|
|
this.gpioPin = pin;
|
|
|
|
try {
|
|
fs.accessSync(gpioPath);
|
|
} catch( e )
|
|
{
|
|
throw new GPIOError("GPIO not accessible");
|
|
}
|
|
|
|
// Überprüfe, ob der GPIO-Pin bereits exportiert ist
|
|
if (!fs.existsSync(gpioPath)) {
|
|
this.export();
|
|
}
|
|
|
|
// Setze den Richtungsmodus auf Ausgang
|
|
fs.writeFileSync(`${gpioPath}/direction`, direction);
|
|
GPIO.openPorts.push(this);
|
|
}
|
|
|
|
public static getPin(pin: number, direction: 'in' | 'out'): GPIO {
|
|
let port = new GPIO(pin, direction);
|
|
this.openPorts.push(port);
|
|
return port;
|
|
}
|
|
|
|
public static watchForButton(pin: number, onPress: (pin: number) => void) {
|
|
const button = new GPIO(pin, 'in');
|
|
this.openPorts.push(button);
|
|
|
|
|
|
button.watch((err) => {
|
|
if (err) {
|
|
console.error(err);
|
|
return;
|
|
}
|
|
|
|
onPress(pin);
|
|
}, 100, 500);
|
|
}
|
|
|
|
public static unexportAll() {
|
|
for (let p of this.openPorts) {
|
|
try {
|
|
p.unexport();
|
|
} catch (e) {
|
|
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
public getValue(): number {
|
|
// Überprüfe, ob der GPIO-Pin bereits exportiert ist
|
|
if (!fs.existsSync(this.gpioPath)) {
|
|
throw new GPIOError('Pin not exported');
|
|
}
|
|
|
|
// Lese den Wert des GPIO-Pins
|
|
const value = fs.readFileSync(`${this.gpioPath}/value`, 'utf8');
|
|
|
|
return Number.parseInt(value.trim());
|
|
}
|
|
|
|
public setValue(value: number) {
|
|
// Setze den Wert auf X
|
|
fs.writeFileSync(`${(this.gpioPath)}/value`, String(value));
|
|
}
|
|
|
|
public setHigh() {
|
|
this.setValue(1);
|
|
}
|
|
|
|
public setLow() {
|
|
this.setValue(0);
|
|
}
|
|
|
|
public changeDirection(direction: 'in' | 'out') {
|
|
// Setze den Richtungsmodus auf Ausgang
|
|
fs.writeFileSync(`${this.gpioPath}/direction`, direction);
|
|
}
|
|
|
|
public watch(callback: (value: number) => void, interval: number = 100, bounceWait = 500) {
|
|
let lastState = this.getValue();
|
|
let lastBounce = Date.now();
|
|
setInterval(() => {
|
|
if (lastBounce + bounceWait > Date.now())
|
|
return;
|
|
|
|
let val = this.getValue();
|
|
if (lastState != val) {
|
|
callback(val);
|
|
lastState = val;
|
|
}
|
|
|
|
}, interval);
|
|
}
|
|
|
|
private export() {
|
|
// Exportiere den GPIO-Pin
|
|
fs.writeFileSync('/sys/class/gpio/export', this.gpioPin.toString());
|
|
}
|
|
|
|
private unexport() {
|
|
// Exportiere den GPIO-Pin
|
|
fs.writeFileSync('/sys/class/gpio/unexport', this.gpioPin.toString());
|
|
}
|
|
|
|
|
|
}
|
|
|
|
export class GPIOError extends Error {
|
|
constructor(msg: string) {
|
|
super(msg);
|
|
|
|
// Set the prototype explicitly.
|
|
Object.setPrototypeOf(this, GPIOError.prototype);
|
|
}
|
|
} |