Skip to content

Commit

Permalink
Replace PIGPIO with RPIO
Browse files Browse the repository at this point in the history
  • Loading branch information
luis-godinez committed Aug 11, 2024
1 parent 2cebb00 commit d64bd62
Show file tree
Hide file tree
Showing 5 changed files with 103 additions and 41 deletions.
6 changes: 5 additions & 1 deletion jest.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export default {
'ts-jest',
{
useESM: true,
tsconfig: 'tsconfig.json', // Points to your tsconfig.json
tsconfig: '<rootDir>/tsconfig.json',
},
],
},
Expand All @@ -18,4 +18,8 @@ export default {
verbose: true,
setupFilesAfterEnv: ['<rootDir>/src/jest.setup.ts'],
modulePathIgnorePatterns: ['<rootDir>/dist/'], // Ignore dist directory
// existing config options
moduleNameMapper: {
'^(\\.{1,2}/.*)\\.js$': '$1', // Strip .js extension for TypeScript files
},
};
48 changes: 32 additions & 16 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
"@types/i2c-bus": "^5.1.2",
"@types/jest": "^29.5.12",
"@types/node": "^20.14.14",
"@types/rpio": "^2.4.6",
"@typescript-eslint/eslint-plugin": "^7.17.0",
"@typescript-eslint/parser": "^7.17.0",
"babel-jest": "^29.7.0",
Expand All @@ -43,15 +44,15 @@
"jest": "^29.7.0",
"mcp-spi-adc": "^3.2.0",
"nodemon": "^3.1.4",
"pigpio": "^3.3.1",
"rimraf": "^6.0.1",
"rpio": "^2.4.2",
"ts-jest": "^29.2.4",
"ts-node": "^10.9.2",
"typescript": "^5.5.4"
},
"dependencies": {
"i2c-bus": "^5.2.3",
"mcp-spi-adc": "^3.2.0",
"pigpio": "^3.3.1"
"rpio": "^2.4.2"
}
}
2 changes: 1 addition & 1 deletion src/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"hasLight": true,
"hasFan": true,
"inverseSaunaDoor": false,
"inverseSteamDoor": true,
"inverseSteamDoor": false,
"temperatureUnitFahrenheit": false,
"gpioPins": {
"saunaPowerPins": [16, 20],
Expand Down
83 changes: 62 additions & 21 deletions src/platformAccessory.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Import necessary modules
import { Service, PlatformAccessory, CharacteristicValue } from 'homebridge';
import { OpenSaunaPlatform } from './platform.js';
import { Gpio } from 'pigpio'; // Updated import from pigpio
import rpio from 'rpio'; // Updated import to use rpio
import { openMcp3008, McpInterface, McpReading, EightChannels } from 'mcp-spi-adc';
import i2c from 'i2c-bus'; // Assume types declared in typings.d.ts
import { OpenSaunaConfig, AuxSensorConfig } from './settings.js';
Expand All @@ -21,7 +21,6 @@ export class OpenSaunaAccessory {
private steamDoorSensor?: Service;
private auxTemperatureSensors: Map<string, Service> = new Map();

private gpioPins: Gpio[] = [];
private adc!: McpInterface; // Define adc as McpInterface
private i2cBus!: i2c.PromisifiedBus; // Define i2cBus

Expand All @@ -38,7 +37,6 @@ export class OpenSaunaAccessory {
// Validate sensor configuration
this.validateSensorConfiguration();

// Initialize the ADC
// Initialize the ADC using openMcp3008
openMcp3008(0, { speedHz: 1350000 }, (error: string) => {
if (error) {
Expand All @@ -64,6 +62,19 @@ export class OpenSaunaAccessory {

// Initialize all necessary services based on the type of accessory
this.setupAccessory();

// Ensure GPIO pins are cleaned up on process exit
process.on('exit', this.cleanupGpioPins.bind(this));
process.on('SIGINT', () => {
// Handle Ctrl+C signal
this.cleanupGpioPins();
process.exit();
});
process.on('SIGTERM', () => {
// Handle termination signal
this.cleanupGpioPins();
process.exit();
});
}

private validateSensorConfiguration() {
Expand All @@ -85,7 +96,45 @@ export class OpenSaunaAccessory {
}
}

// Initialize GPIO pins during setup
private initializeGpioPins() {
this.config.gpioPins.saunaPowerPins.forEach((pin) => rpio.open(pin, rpio.OUTPUT, rpio.LOW));
this.config.gpioPins.steamPowerPins.forEach((pin) => rpio.open(pin, rpio.OUTPUT, rpio.LOW));
if (this.config.gpioPins.lightPin !== undefined) {
rpio.open(this.config.gpioPins.lightPin, rpio.OUTPUT, rpio.LOW);
}
if (this.config.gpioPins.fanPin !== undefined) {
rpio.open(this.config.gpioPins.fanPin, rpio.OUTPUT, rpio.LOW);
}
if (this.config.gpioPins.saunaDoorPin !== undefined) {
rpio.open(this.config.gpioPins.saunaDoorPin, rpio.INPUT, rpio.PULL_DOWN); // Or PULL_UP, as needed
}
if (this.config.gpioPins.steamDoorPin !== undefined) {
rpio.open(this.config.gpioPins.steamDoorPin, rpio.INPUT, rpio.PULL_DOWN); // Or PULL_DOWN, as needed
}
}

// Close GPIO pins during cleanup
private cleanupGpioPins() {
this.config.gpioPins.saunaPowerPins.forEach((pin) => rpio.close(pin));
this.config.gpioPins.steamPowerPins.forEach((pin) => rpio.close(pin));
if (this.config.gpioPins.lightPin !== undefined) {
rpio.close(this.config.gpioPins.lightPin);
}
if (this.config.gpioPins.fanPin !== undefined) {
rpio.close(this.config.gpioPins.fanPin);
}
if (this.config.gpioPins.saunaDoorPin !== undefined) {
rpio.close(this.config.gpioPins.saunaDoorPin);
}
if (this.config.gpioPins.steamDoorPin !== undefined) {
rpio.close(this.config.gpioPins.steamDoorPin);
}
}

private setupAccessory() {
this.initializeGpioPins();

// Setup switches
this.saunaPowerSwitch =
this.accessory.getService('Sauna Power') ||
Expand Down Expand Up @@ -226,6 +275,7 @@ export class OpenSaunaAccessory {
this.monitorTemperatures();
this.monitorHumidity();
this.monitorDoors();
process.on('exit', this.cleanupGpioPins.bind(this));
}

// Handle power switch onSet events
Expand All @@ -248,18 +298,14 @@ export class OpenSaunaAccessory {
private handleLightPowerSet(value: CharacteristicValue) {
this.platform.log.info('Light Power set to:', value);
if (this.config.gpioPins.lightPin !== undefined) {
const gpio = new Gpio(this.config.gpioPins.lightPin, {
mode: Gpio.OUTPUT,
});
gpio.digitalWrite(value ? 1 : 0);
rpio.write(this.config.gpioPins.lightPin, value ? rpio.HIGH : rpio.LOW);
}
}

private handleFanPowerSet(value: CharacteristicValue) {
this.platform.log.info('Fan Power set to:', value);
if (this.config.gpioPins.fanPin !== undefined) {
const gpio = new Gpio(this.config.gpioPins.fanPin, { mode: Gpio.OUTPUT });
gpio.digitalWrite(value ? 1 : 0);
rpio.write(this.config.gpioPins.fanPin, value ? rpio.HIGH : rpio.LOW);
}
}

Expand Down Expand Up @@ -302,10 +348,11 @@ export class OpenSaunaAccessory {

// Utility to set power state on GPIO
private setPowerState(pins: number[], state: CharacteristicValue) {
const powerState = state ? 1 : 0;
const powerState = state ? rpio.HIGH : rpio.LOW;
pins.forEach((pin) => {
const gpio = new Gpio(pin, { mode: Gpio.OUTPUT });
gpio.digitalWrite(powerState);
rpio.open(pin, rpio.OUTPUT);
rpio.write(pin, powerState);
rpio.close(pin);
});
}

Expand Down Expand Up @@ -521,9 +568,8 @@ export class OpenSaunaAccessory {

doorSensors.forEach(({ type, pin, inverse, allowOnWhileOpen, powerPins }) => {
if (pin !== undefined) {
const doorSensor = new Gpio(pin, { mode: Gpio.INPUT, alert: true });
doorSensor.on('alert', (level) => {
const doorOpen = inverse ? level === 0 : level === 1;
rpio.poll(pin, () => {
const doorOpen = inverse ? rpio.read(pin) === 0 : rpio.read(pin) === 1;
this.platform.log.info(
`${type.charAt(0).toUpperCase() + type.slice(1)} Door ${
doorOpen ? 'Open' : 'Closed'
Expand Down Expand Up @@ -552,12 +598,7 @@ export class OpenSaunaAccessory {
this.setPowerState(powerPins, true);
this.platform.log.info(`${type} power resumed as door closed.`);
}
});

// Clean up on shutdown
process.on('exit', () => {
doorSensor.digitalWrite(0); // Ensure the pin is in a safe state
});
}, rpio.POLL_BOTH); // Ensure both rising and falling edges are detected
} else {
this.platform.log.warn(`No door pin configured for ${type}`);
}
Expand Down

0 comments on commit d64bd62

Please sign in to comment.