Files
actest/CO2_SENSOR_INTEGRATION.md
sebseb7 6944111f84 u
2025-12-21 01:06:59 +01:00

3.7 KiB

CO2 Sensor Integration Guide

This document explains how to write CO2 sensor data directly to the ac_data.db SQLite database so it appears under the "Wall" device on the dashboard.

Database Location

/home/seb/src/actest/ac_data.db

Current Schema

CREATE TABLE readings (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    timestamp DATETIME DEFAULT CURRENT_TIMESTAMP,
    dev_id TEXT,
    dev_name TEXT,
    port INTEGER,
    port_name TEXT,
    temp_c REAL,
    humidity REAL,
    vpd REAL,
    fan_speed INTEGER,
    on_speed INTEGER,
    off_speed INTEGER
);

Inserting CO2 Data

Add CO2 readings as a new port on the "Wall" device. Use port 2 with port_name = 'CO2'.

SQL Insert Statement

INSERT INTO readings (dev_name, port, port_name, temp_c, humidity, vpd, fan_speed)
VALUES ('Wall', 2, 'CO2', NULL, NULL, NULL, <CO2_VALUE_PPM>);

Note

: The fan_speed column stores the CO2 ppm value. This reuses the existing integer column for sensor readings.

Example: Insert 850 ppm

INSERT INTO readings (dev_name, port, port_name, temp_c, humidity, vpd, fan_speed)
VALUES ('Wall', 2, 'CO2', NULL, NULL, NULL, 850);

From Command Line (bash)

sqlite3 /home/seb/src/actest/ac_data.db \
  "INSERT INTO readings (dev_name, port, port_name, fan_speed) VALUES ('Wall', 2, 'CO2', 850);"

From Node.js

import Database from 'better-sqlite3';

const db = new Database('/home/seb/src/actest/ac_data.db');

function insertCO2Reading(ppm) {
    const stmt = db.prepare(`
        INSERT INTO readings (dev_name, port, port_name, fan_speed)
        VALUES ('Wall', 2, 'CO2', ?)
    `);
    stmt.run(ppm);
}

// Example: Insert reading
insertCO2Reading(850);

From Python

import sqlite3

DB_PATH = '/home/seb/src/actest/ac_data.db'

def insert_co2_reading(ppm):
    conn = sqlite3.connect(DB_PATH)
    cursor = conn.cursor()
    cursor.execute('''
        INSERT INTO readings (dev_name, port, port_name, fan_speed)
        VALUES ('Wall', 2, 'CO2', ?)
    ''', (ppm,))
    conn.commit()
    conn.close()

# Example: Insert reading
insert_co2_reading(850)

Dashboard Display

Once data is inserted, the dashboard will automatically:

  1. Detect "Wall" device now has 2 ports: Fan (port 1) and CO2 (port 2)
  2. Display a new chart card labeled "CO2" under the Wall controller

Current Limitation

The LevelChart component currently:

  • Uses fan_speed for the Y-axis data (works for CO2)
  • Labels chart as "Fan Speed" for non-light ports ⚠️
  • Has Y-axis scale 0-10 ⚠️ (too small for CO2 ppm)

The chart will display CO2 data, but the label and scale won't be ideal.

To properly display CO2 data, modify src/client/LevelChart.js:

// Detect CO2 sensor type
const isCO2 = portName?.toLowerCase().includes('co2');

// Set appropriate label
const levelLabel = isLight ? 'Brightness' : (isCO2 ? 'CO2 (ppm)' : 'Fan Speed');

// Set appropriate Y-axis scale
const yScale = isCO2 
    ? { suggestedMin: 400, suggestedMax: 2000 }
    : { suggestedMin: 0, suggestedMax: 10, ticks: { stepSize: 1 } };

Testing

After inserting test data, verify it appears:

# Check if data was inserted
sqlite3 /home/seb/src/actest/ac_data.db \
  "SELECT * FROM readings WHERE port_name = 'CO2' ORDER BY timestamp DESC LIMIT 5;"

# View all ports for Wall device
sqlite3 /home/seb/src/actest/ac_data.db \
  "SELECT DISTINCT dev_name, port, port_name FROM readings WHERE dev_name = 'Wall';"

Cron Job Example

To log CO2 every minute from another script:

# crontab -e
* * * * * /path/to/your/co2_logger.sh >> /var/log/co2_logger.log 2>&1

Where co2_logger.sh reads your sensor and inserts to the database.