Skip to content

johnx25bd/huum-js

Repository files navigation

huum-js

TypeScript library for controlling HUUM saunas

npm version TypeScript License: MIT

Features

  • Fully typed - Complete TypeScript support with strict mode
  • Retry logic - Exponential backoff for reliability
  • Safety checks - Door validation before heating
  • Mock client - Testing without hardware
  • Modern - ESM + CJS, async/await, native fetch API
  • Zero dependencies - Lightweight and secure
  • Real API - Based on verified HUUM API testing

Installation

npm install huum-js

Requirements: Node.js 18+ (uses native fetch() API)

Quick Start

import { HuumClient } from 'huum-js';

const client = new HuumClient({
  username: 'your@email.com',
  password: 'your-password'
});

// Start heating
await client.startHeating(80);

// Check status
const status = await client.getStatus();
console.log(`Temperature: ${status.temperatureC}°C`);
console.log(`Door closed: ${status.isDoorClosed}`);
console.log(`Heating: ${status.isHeating}`);

// Stop heating
await client.stopHeating();

API Reference

new HuumClient(credentials, config?)

Creates a new HUUM client instance.

const client = new HuumClient(
  {
    username: 'your@email.com',
    password: 'your-password'
  },
  {
    timeout: 5000,       // Request timeout (ms)
    retryAttempts: 3,    // Number of retries
    safetyChecks: true,  // Check door before heating
    logger: console      // Custom logger
  }
);

client.getStatus(): Promise<HuumStatus>

Gets current sauna status with helpful properties.

const status = await client.getStatus();

// Temperature (parsed as numbers)
console.log(status.temperatureC);        // 52
console.log(status.targetTemperatureC);  // 80

// Status helpers
console.log(status.isHeating);      // true/false
console.log(status.isOnline);       // true/false
console.log(status.isOffline);      // true/false
console.log(status.isDoorClosed);   // true/false
console.log(status.statusText);     // 'heating', 'online', 'offline', etc.

// Raw API fields (as returned by HUUM)
console.log(status.statusCode);     // 231 (heating)
console.log(status.door);           // true (closed)
console.log(status.temperature);    // "52" (string)
console.log(status.targetTemperature); // "80" (string)

Status Codes

Code Meaning Helper
230 Offline status.isOffline
231 Heating status.isHeating
232 Online (not heating) status.isOnline
233 Locked by another user status.isLocked
400 Emergency stop status.isEmergency

client.startHeating(temperature, options?): Promise<HuumStatus>

Starts heating the sauna.

// Basic
await client.startHeating(80);

// With scheduling
await client.startHeating(80, {
  startDate: Math.floor(Date.now() / 1000) + 3600,  // Start in 1 hour
  endDate: Math.floor(Date.now() / 1000) + 7200     // End in 2 hours
});

// With humidifier (if equipped)
await client.startHeating(80, {
  humidity: 5  // Target humidity 0-10
});

Parameters:

  • temperature (40-110): Target temperature in Celsius
  • options.startDate: Unix timestamp (seconds) to start heating
  • options.endDate: Unix timestamp (seconds) to stop heating
  • options.humidity: Target humidity (0-10, requires humidifier)

Throws:

  • HuumValidationError - Invalid temperature (not 40-110°C)
  • HuumSafetyError - Door is open (when safetyChecks: true)
  • HuumAuthError - Invalid credentials
  • HuumTimeoutError - Request timeout

client.stopHeating(): Promise<HuumStatus>

Stops heating the sauna.

await client.stopHeating();

Error Handling

import {
  HuumClient,
  HuumAuthError,
  HuumSafetyError,
  HuumTimeoutError,
  HuumValidationError,
  HuumNetworkError,
} from 'huum-js';

try {
  await client.startHeating(80);
} catch (error) {
  if (error instanceof HuumAuthError) {
    console.error('Invalid credentials');
  } else if (error instanceof HuumSafetyError) {
    console.error('Door is open');
  } else if (error instanceof HuumValidationError) {
    console.error('Invalid temperature (must be 40-110°C)');
  } else if (error instanceof HuumTimeoutError) {
    console.error('Request timeout');
  } else if (error instanceof HuumNetworkError) {
    console.error('Network error');
  }
}

Mock Client for Testing

Perfect for unit tests, demos, and development without real hardware.

import { MockHuumClient } from 'huum-js/mock';

// No credentials needed!
const client = new MockHuumClient();

// Works exactly like HuumClient
const status = await client.getStatus();
await client.startHeating(80);
await client.stopHeating();

// Test utilities
client.setDoorOpen(true);       // Simulate door opening
client.setTemperature(65);      // Set temperature directly
client.reset();                 // Reset to default state

The mock client simulates realistic behavior:

  • ✅ Temperature rises/falls over time
  • ✅ Status codes change (heating → online)
  • ✅ Door safety checks work
  • ✅ Returns exact same field names as real API

Advanced Usage

Custom Configuration

const client = new HuumClient(
  { username: 'user@example.com', password: 'pass' },
  {
    timeout: 10000,        // 10 second timeout
    retryAttempts: 5,      // Retry 5 times
    safetyChecks: true,    // Check door before heating
    logger: {
      info: (msg, meta) => console.log(`[INFO] ${msg}`, meta),
      error: (msg, meta) => console.error(`[ERROR] ${msg}`, meta),
      warn: (msg, meta) => console.warn(`[WARN] ${msg}`, meta),
    }
  }
);

Monitoring Temperature

async function waitForTemperature(targetTemp: number) {
  while (true) {
    const status = await client.getStatus();
    console.log(`Current: ${status.temperatureC}°C`);

    if (status.temperatureC >= targetTemp) {
      console.log('Target reached!');
      break;
    }

    await new Promise(resolve => setTimeout(resolve, 30000)); // Wait 30s
  }
}

await client.startHeating(80);
await waitForTemperature(80);

Examples

See the examples/ directory for complete, runnable examples:

API Details

Based on real HUUM API testing (verified 2025-10-11). See REAL_API_SCHEMA.md for full details.

Key Findings

  • Field naming: API uses camelCase (targetTemperature, statusCode)
  • Temperature fields: Returned as strings, parsed to numbers by helper methods
  • Door field: Boolean (true = closed, false = open)
  • Timestamps: Unix timestamps in seconds

Development

This library was extracted from a production HUUM integration and tested against real hardware.

Differences from pyhuum:

  • ✅ TypeScript with full type safety
  • ✅ Modern ESM + CJS builds
  • ✅ Field names match actual API (pyhuum converts to snake_case)
  • ✅ Mock client included for testing
  • ✅ Helper methods for common operations

Related Projects

Contributing

Contributions welcome! This library aims to be:

  • Accurate: Match real HUUM API exactly
  • Type-safe: Full TypeScript coverage
  • Well-tested: High test coverage
  • Well-documented: Clear examples and API docs

Safety & Disclaimer

WARNING: This library controls physical heating equipment.

  • Always monitor your sauna while heating
  • Ensure proper ventilation and safety systems are functional
  • Never leave heating equipment unattended
  • This is unofficial software not endorsed by HUUM

Use at your own risk. This software is provided "AS IS" without warranty. The authors and Sophia Systems Corporation are not liable for any damages, injuries, or equipment failures.

License

MIT © Sophia Systems Corporation

Acknowledgments

  • Thanks to frwickst/pyhuum for Python implementation
  • HUUM for providing third-party API access
  • Tested against real HUUM Drop sauna with UKU Wi-Fi control

Note: This library requires valid HUUM credentials. Use the mock client for testing without hardware.

About

TypeScript library for controlling HUUM saunas

Resources

License

Stars

2 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors