From 30b65b2a2c27bb8128b62c3b2a18a493f824a928 Mon Sep 17 00:00:00 2001 From: Luis Godinez Date: Sun, 18 Aug 2024 15:47:18 -0700 Subject: [PATCH] Revert "import mcp-spi-ads module" This reverts commit 254c8cd6045b21dc820e1271bc8c583e8f1a0b1d. --- src/config.json | 2 +- src/platformAccessory.ts | 35 ++---- src/typings.d.ts | 263 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 275 insertions(+), 25 deletions(-) create mode 100644 src/typings.d.ts diff --git a/src/config.json b/src/config.json index 554023c..02e7bfd 100644 --- a/src/config.json +++ b/src/config.json @@ -62,7 +62,7 @@ }, { "name": "STEAM_NTC", - "channel": 2, + "channel": 1, "system": "steam", "control": true, "resistanceAt25C": 10000, diff --git a/src/platformAccessory.ts b/src/platformAccessory.ts index 82ceb21..49f5e94 100644 --- a/src/platformAccessory.ts +++ b/src/platformAccessory.ts @@ -3,7 +3,7 @@ import { Service, PlatformAccessory, CharacteristicValue } from 'homebridge'; import { OpenSaunaPlatform } from './platform.js'; import rpio from 'rpio'; -const mcpSpiAdc = require('mcp-spi-adc'); +import { openMcp3008, McpInterface, McpReading, EightChannels } from 'mcp-spi-adc'; import i2c from 'i2c-bus'; import { OpenSaunaConfig, AuxSensorConfig, SystemType } from './settings.js'; @@ -13,7 +13,7 @@ export class OpenSaunaAccessory { private steamTemperatureSensor?: Service; private lightPowerSwitch?: Service; private fanPowerSwitch?: Service; - private adc!: any; // Updated to any since we're using require + private adc!: McpInterface; private i2cBus!: i2c.PromisifiedBus; private saunaTimer: NodeJS.Timeout | null = null; private steamTimer: NodeJS.Timeout | null = null; @@ -79,32 +79,19 @@ export class OpenSaunaAccessory { private validateSensorConfiguration() { const systemCount: { [key: string]: number } = {}; - const channelSet = new Set(); // To track used channels this.config.auxSensors.forEach((sensor) => { - // Check for duplicate system configuration if (sensor.system) { if (!systemCount[sensor.system]) { systemCount[sensor.system] = 0; } systemCount[sensor.system]++; } - - // Check for duplicate channels - if (channelSet.has(sensor.channel)) { - throw new Error( - `Duplicate channel detected: Channel ${sensor.channel} is already used by another sensor. Each sensor must have a unique channel.`, - ); - } - channelSet.add(sensor.channel); }); - // Ensure only one NTC sensor per system for (const system in systemCount) { if (systemCount[system] > 1) { - throw new Error( - `Only one NTC sensor is allowed for the ${system} system.`, - ); + throw new Error(`Only one NTC sensor is allowed for the ${system} system.`); } } } @@ -149,7 +136,7 @@ export class OpenSaunaAccessory { reject(new Error('ADC initialization timeout')); }, 5000); // 5-second timeout - this.adc = mcpSpiAdc.openMcp3008(0, { speedHz: 1350000 }, (error: any) => { + openMcp3008(0, { speedHz: 1350000 }, (error) => { clearTimeout(timeout); if (error) { this.platform.log.error('Failed to open ADC:', error); @@ -568,23 +555,23 @@ export class OpenSaunaAccessory { // Monitor temperatures using ADC channels private monitorTemperatures() { this.config.auxSensors.forEach((sensor) => { - const adcChannel = sensor.channel; + const adcChannel = sensor.channel as EightChannels; // Open ADC channel for each sensor - this.adc = mcpSpiAdc.openMcp3008(adcChannel, { speedHz: 1350000 }, (err: any) => { + this.adc = openMcp3008(adcChannel, { speedHz: 1350000 }, (err: string) => { if (err) { this.platform.log.error( - `Failed to open ADC channel ${adcChannel} for sensor "${sensor.name}": ${err}`, + `Failed to open ADC channel ${adcChannel} for sensor "${sensor.system}": ${err}`, ); return; } // Set up a regular interval to read from the ADC channel const interval = setInterval(() => { - this.adc.read((err: any, reading: any) => { + this.adc.read((err: string | null, reading: McpReading) => { if (err) { this.platform.log.error( - `Failed to read temperature for sensor "${sensor.name}": ${err}`, + `Failed to read temperature for sensor "${sensor.system}": ${err}`, ); return; } @@ -603,7 +590,7 @@ export class OpenSaunaAccessory { const isInvalidReading = temperatureCelsius < -20 || temperatureCelsius > 150; if (isInvalidReading) { this.platform.log.warn( - `${sensor.name} Invalid Temperature: ${displayTemperature.toFixed(2)} °${ + `${sensor.system} Invalid Temperature: ${displayTemperature.toFixed(2)} °${ this.config.temperatureUnitFahrenheit ? 'F' : 'C' }`, ); @@ -611,7 +598,7 @@ export class OpenSaunaAccessory { this.reflectInvalidReadingState(sensor); return; } else { - this.platform.log.info(`[Temp] ${sensor.name}:${temperatureCelsius}`); + this.platform.log.info(`[Temp] ${sensor.system}:${temperatureCelsius}`); } // Update the HomeKit characteristic with the current temperature diff --git a/src/typings.d.ts b/src/typings.d.ts new file mode 100644 index 0000000..3d3777e --- /dev/null +++ b/src/typings.d.ts @@ -0,0 +1,263 @@ +declare module 'onoff' { + // Custom type definition + export type GpioCallback = (err: Error | null | undefined, value: number) => void; +} + +/** + * Library for interacting with MCP3XXX devices + * + * Supported devices: + * + * MCP300X: MCP3002 MCP3004 MCP3008 + * + * MCP320X: MCP3202 MCP3204 MCP3208 + * + * MCP330X: MCP3304 + */ +declare module 'mcp-spi-adc' { + export type EightChannels = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7; + + export type FourChannels = 0 | 1 | 2 | 3; + + export type TwoChannels = 0 | 1; + + export type Channels = EightChannels | FourChannels | TwoChannels; + + /** + * Connect to an MCP3008 ADC + * ([Datasheet](https://ww1.microchip.com/downloads/en/DeviceDoc/21295d.pdf)) + * + * @param channel Zero-indexed output channel number + * @param options Configuration values that can be overloaded + * @param callback Called after establishing a connection to the device + */ + export function open( + channel: EightChannels, + options: McpOptions, + callback: (error: string) => void + ): McpInterface; + + /** + * Connect to an MCP3008 ADC using the default options + * ([Datasheet](https://ww1.microchip.com/downloads/en/DeviceDoc/21295d.pdf)) + * + * @param channel Zero-indexed output channel number + * @param callback Called after establishing a connection to the device + */ + export function open(channel: EightChannels, callback: (error: string) => void): McpInterface; + + /** + * Connect to an MCP3008 ADC + * ([Datasheet](https://ww1.microchip.com/downloads/en/DeviceDoc/21295d.pdf)) + * + * @param channel Zero-indexed output channel number + * @param options Configuration values that can be overloaded + * @param callback Called after establishing a connection to the device + */ + export function openMcp3008( + channel: EightChannels, + options: McpOptions, + callback: (error: string) => void + ): McpInterface; + + /** + * Connect to an MCP3008 ADC using the default options + * ([Datasheet](https://ww1.microchip.com/downloads/en/DeviceDoc/21295d.pdf)) + * + * @param channel Zero-indexed output channel number + * @param callback Called after establishing a connection to the device + */ + export function openMcp3008( + channel: EightChannels, + callback: (error: string) => void + ): McpInterface; + + /** + * Connect to an MCP3004 ADC + * ([Datasheet](https://ww1.microchip.com/downloads/en/DeviceDoc/21295d.pdf)) + * + * @param channel Zero-indexed output channel number + * @param options Configuration values that can be overloaded + * @param callback Called after establishing a connection to the device + */ + export function openMcp3004( + channel: FourChannels, + options: McpOptions, + callback: (error: string) => void + ): McpInterface; + + /** + * Connect to an MCP3002 ADC using the default options + * ([Datasheet](https://ww1.microchip.com/downloads/en/DeviceDoc/21295d.pdf)) + * + * @param channel Zero-indexed output channel number + * @param callback Called after establishing a connection to the device + */ + export function openMcp3004( + channel: FourChannels, + callback: (error: string) => void + ): McpInterface; + + /** + * Connect to an MCP3002 ADC + * ([Datasheet](https://ww1.microchip.com/downloads/en/DeviceDoc/21294E.pdf)) + * + * @param channel Zero-indexed output channel number + * @param options Configuration values that can be overloaded + * @param callback Called after establishing a connection to the device + */ + export function openMcp3002( + channel: TwoChannels, + options: McpOptions, + callback: (error: string) => void + ): McpInterface; + + /** + * Connect to an MCP3002 ADC using the default options + * ([Datasheet](https://ww1.microchip.com/downloads/en/DeviceDoc/21294E.pdf)) + * + * @param channel Zero-indexed output channel number + * @param callback Called after establishing a connection to the device + */ + export function openMcp3002( + channel: TwoChannels, + callback: (error: string) => void + ): McpInterface; + + /** + * Connect to an MCP3202 ADC + * ([Datasheet](https://ww1.microchip.com/downloads/en/DeviceDoc/21294E.pdf)) + * + * @param channel Zero-indexed output channel number + * @param options Configuration values that can be overloaded + * @param callback Called after establishing a connection to the device + */ + export function openMcp3202( + channel: TwoChannels, + options: McpOptions, + callback: (error: string) => void + ): McpInterface; + + /** + * Connect to an MCP3202 ADC using the default options + * ([Datasheet](https://ww1.microchip.com/downloads/en/DeviceDoc/21294E.pdf)) + * + * @param channel Zero-indexed output channel number + * @param callback Called after establishing a connection to the device + */ + export function openMcp3202( + channel: TwoChannels, + callback: (error: string) => void + ): McpInterface; + + /** + * Connect to an MCP3204 ADC + * ([Datasheet]https://ww1.microchip.com/downloads/en/DeviceDoc/21298e.pdf)) + * + * @param channel Zero-indexed output channel number + * @param options Configuration values that can be overloaded + * @param callback Called after establishing a connection to the device + */ + export function openMcp3204( + channel: FourChannels, + options: McpOptions, + callback: (error: string) => void + ): McpInterface; + + /** + * Connect to an MCP3204 ADC using the default options + * ([Datasheet](https://ww1.microchip.com/downloads/en/DeviceDoc/21298e.pdf)) + * + * @param channel Zero-indexed output channel number + * @param callback Called after establishing a connection to the device + */ + export function openMcp3204( + channel: FourChannels, + callback: (error: string) => void + ): McpInterface; + + /** + * Connect to an MCP3208 ADC + * ([Datasheet](https://ww1.microchip.com/downloads/en/DeviceDoc/21298e.pdf)) + * + * @param channel Zero-indexed output channel number + * @param options Configuration values that can be overloaded + * @param callback Called after establishing a connection to the device + */ + export function openMcp3208( + channel: EightChannels, + options: McpOptions, + callback: (error: string) => void + ): McpInterface; + + /** + * Connect to an MCP3208 ADC using the default options + * ([Datasheet](https://ww1.microchip.com/downloads/en/DeviceDoc/21298e.pdf)) + * + * @param channel Zero-indexed output channel number + * @param callback Called after establishing a connection to the device + */ + export function openMcp3208( + channel: EightChannels, + callback: (error: string) => void + ): McpInterface; + + /** + * Connect to an MCP3304 ADC + * ([Datasheet](https://ww1.microchip.com/downloads/en/DeviceDoc/21697F.pdf)) + * + * @param channel Zero-indexed output channel number + * @param options Configuration values that can be overloaded + * @param callback Called after establishing a connection to the device + */ + export function openMcp3304( + channel: EightChannels, + options: McpOptions, + callback: (error: string) => void + ): McpInterface; + + /** + * Connect to an MCP3304 ADC using the default options + * ([Datasheet](https://ww1.microchip.com/downloads/en/DeviceDoc/21697F.pdf)) + * + * @param channel Zero-indexed output channel number + * @param callback Called after establishing a connection to the device + */ + export function openMcp3304( + channel: EightChannels, + callback: (error: string) => void + ): McpInterface; + + /** + * SPI device surface area for interacting with the MCP3XXX device + */ + export interface McpInterface { + /** + * Query the device for the current reading + * @param callback Called after the read command has completed + */ + read(callback: (error: string, reading: McpReading) => void): void; + + /** + * Sever communication with the MCP3XXX device + * @param callback Called after communication has been stopped + */ + close(callback: (error: string) => void): void; + } + + export interface McpReading { + /* Device reading normalized in the range [0, 1] */ + value: number; + /* Raw counts received from the device */ + rawValue: number; + } + + interface McpOptions { + /* SPI clock frequency for reaching from the channel */ + speedHz?: number; + /* SPI bus number, e.g. /dev/spidev0.X*/ + busNumber?: number; + /* Spi device number, e.g. /dev/spidevX.0 */ + deviceNumber?: C; + } +}