seperate lights/heat

This commit is contained in:
David Westgate 2025-04-20 03:48:53 +01:00
parent 22aeed01be
commit e10a492910
6 changed files with 94 additions and 57 deletions

View File

@ -1,9 +1,12 @@
{ {
"dependencies": { "dependencies": {
"@roamhq/wrtc": "0.8.0", "@roamhq/wrtc": "0.8.0",
"node-dht-sensor": "^0.4.5",
"node-pre-gyp": "^0.17.0", "node-pre-gyp": "^0.17.0",
"ws": "^8.18.0", "pigpio": "^3.3.1",
"sass": "1.86.3" "sass": "1.86.3",
"serialport": "^13.0.0",
"ws": "^8.18.0"
}, },
"scripts": { "scripts": {
"build:scss": "npx sass src/static/css:dist/static/css", "build:scss": "npx sass src/static/css:dist/static/css",
@ -16,6 +19,7 @@
}, },
"devDependencies": { "devDependencies": {
"@types/node": "^22.10.2", "@types/node": "^22.10.2",
"@types/node-dht-sensor": "^0.4.2",
"@types/ws": "^8.5.13", "@types/ws": "^8.5.13",
"ts-node": "^10.9.2", "ts-node": "^10.9.2",
"typescript": "^5.8.2" "typescript": "^5.8.2"

View File

@ -1,5 +1,6 @@
import Serial from "./serial"; import Serial from "./serial";
import * as pigpio from 'pigpio'; import * as pigpio from 'pigpio';
import * as dht from 'node-dht-sensor';
type ONOFF = 0 | 1; type ONOFF = 0 | 1;
const ON: ONOFF = 0 const ON: ONOFF = 0
@ -9,61 +10,69 @@ const OFF: ONOFF = 1
export interface ISensors { export interface ISensors {
temperature: number; temperature: number;
power: boolean; lights: boolean;
moisture: number; heat: boolean
moisture0: number;
moisture1: number;
humidity: number; humidity: number;
} }
export default class IO implements ISensors { export default class IO {
temperature: number; gpioLights: pigpio.Gpio
moisture: number; gpioHeat: pigpio.Gpio
humidity: number;
gpio: pigpio.Gpio
serial: Serial; serial: Serial;
power: boolean; lights: boolean;
getMoisture : ()=>number; heat: boolean;
getMoisture: () => ({ moisture0: number, moisture1: number });
public constructor(POWER_GPIO = 17) { public constructor(LIGHTS_GPIO = 17, HEAT_GPIO=22, DHT_GPIO = 27, DHT_MODEL = 22) {
const serial = new Serial() const serial = new Serial()
this.getMoisture = serial.getMoisture.bind(serial); this.getMoisture = serial.getMoisture.bind(serial);
this.serial = serial; this.serial = serial;
// Initialize pigpio and the GPIO pin
const read = new pigpio.Gpio(POWER_GPIO, {mode: pigpio.Gpio.INPUT});
this.power = read.digitalRead() == ON ? true : false
this.gpio = new pigpio.Gpio(POWER_GPIO, { mode: pigpio.Gpio.OUTPUT });
this.humidity = 0 const readLights = new pigpio.Gpio(LIGHTS_GPIO, { mode: pigpio.Gpio.INPUT });
this.temperature = 0; this.lights = readLights.digitalRead() == ON ? true : false
// this.serial.getMoisture.bind(this) this.gpioLights = new pigpio.Gpio(LIGHTS_GPIO, { mode: pigpio.Gpio.OUTPUT });
const readHeat = new pigpio.Gpio(HEAT_GPIO, { mode: pigpio.Gpio.INPUT });
this.lights = readHeat.digitalRead() == ON ? true : false
this.gpioHeat = new pigpio.Gpio(HEAT_GPIO, { mode: pigpio.Gpio.OUTPUT });
dht.initialize(22, DHT_GPIO);
dht.setMaxRetries(10);
} }
public setPower(state: boolean, GPIO= 17) {
if(GPIO == 17){
this.lights = state;
this.gpioLights.digitalWrite(this.lights ? ON : OFF);
}
else if(GPIO == 22){
this.heat = state;
this.gpioHeat.digitalWrite(this.heat ? ON : OFF);
}
// getPower() { }
// // Read the current state of the GPIO pin
// return this.gpio.digitalRead() === ON; // public togglePower() {
// this.power = !this.power;
// this.gpio.digitalWrite(this.power ? ON : OFF);
// } // }
public setPower(power: boolean) { private round = (n) =>
// Set the GPIO pin to high (1) or low (0) (n * 100) / 100
this.power = power;
this.gpio.digitalWrite(this.power ? ON : OFF);
}
public togglePower() {
// Toggle the power state (turn the pin on or off)
this.power = !this.power;
this.gpio.digitalWrite(this.power ? ON : OFF);
}
public getSensors(): ISensors { public getSensors(): ISensors {
// console.log("serial ", ) const { temperature, humidity } = dht.read(22, 27)
const { moisture0, moisture1 } = this.getMoisture()
return { return {
power: this.power, lights: this.lights,
moisture: this.getMoisture(), heat: this.heat,
temperature: this.temperature, moisture0: moisture0,
humidity: this.humidity moisture1: moisture1,
temperature: this.round(temperature),
humidity: this.round(humidity)
} }
} }
} }

View File

@ -14,25 +14,29 @@ export default class Serial {
const readline = new serialport.ReadlineParser({ delimiter }); const readline = new serialport.ReadlineParser({ delimiter });
const parser = port.pipe(readline); const parser = port.pipe(readline);
parser.on('data', line => { parser.on('data', line => {
// console.log("data line ", line)
const data = JSON.parse(line) const data = JSON.parse(line)
const moisture0 = parseInt(data['A0'], 10); const moisture0 = parseInt(data['A0'], 10);
const moisture1 = parseInt(data['A1'], 10); const moisture1 = parseInt(data['A1'], 10);
if (!isNaN(moisture0) && !isNaN(moisture1)) { if (!isNaN(moisture0) && !isNaN(moisture1)) {
// console.log("m ", this.moisture)
this.moisture0 = moisture0; this.moisture0 = moisture0;
this.moisture1 = moisture1; this.moisture1 = moisture1;
} }
else { else {
console.log("data ",data) console.error("Error reading analog data")
} }
}); });
port.on('error', err => { port.on('error', err => {
console.error('Serial Error:', err.message); console.error('Serial Error:', err.message);
}); });
} }
private scale = (value: number) => {
const percent = (value / 1024) * 100;
return Math.min(Math.max(percent, 0), 100); // Clamp to 0-100 just in case
}
public getMoisture() { public getMoisture() {
return this.moisture0; return { moisture0: this.scale(this.moisture0), moisture1: this.scale(this.moisture1) };
} }

View File

@ -42,7 +42,7 @@ httpServer.start();
process.stdin.setEncoding("utf8"); process.stdin.setEncoding("utf8");
process.stdin.resume(); process.stdin.resume();
console.log("Menu:\n1) Power off\n2)Power on\n3) Power flop\n4)Read Sensors"); console.log("Menu:\n1)Lights Power off\n2) Lights Power on\n3)Heat Power Off\n4) Heat power on\n5)Read Sensors");
process.stdin.on("data", async (data: string) => { process.stdin.on("data", async (data: string) => {
const input = data.trim(); const input = data.trim();
@ -53,16 +53,20 @@ process.stdin.on("data", async (data: string) => {
break; break;
case 1: case 1:
io.setPower(false); io.setPower(false,17);
break; break;
case 2: case 2:
io.setPower(true); io.setPower(true,17);
break; break;
case 3: case 3:
io.togglePower(); io.setPower(false,22);
break; break;
case 4: case 4:
io.setPower(true,22);
break;
case 5:
console.log("a ", getSensors()) console.log("a ", getSensors())
break; break;
default: default:

View File

@ -18,8 +18,12 @@
<video id="video0" autoplay playsinline controls></video> <video id="video0" autoplay playsinline controls></video>
<div id="channel-container-0" class="channel-group"></div> <div id="channel-container-0" class="channel-group"></div>
</div> </div>
<p id="sensors"></p> <div id="data-container">
<button onclick="poll()">Poll</button> <!-- <p id="power"></p>
<p id="moisture"></p>
<p id="temperature"></p>
<p id="humidity"></p> -->
</div>
</main> </main>
</div> </div>

View File

@ -2,6 +2,14 @@ const isSecure = window.location.protocol === 'https:';
const host = window.location.hostname; const host = window.location.hostname;
const ws0builder = isSecure ? `wss://${host}/ws3` : `ws://${host}:3003`; const ws0builder = isSecure ? `wss://${host}/ws3` : `ws://${host}:3003`;
const ws0 = new WebSocket(ws0builder); const ws0 = new WebSocket(ws0builder);
interface IData {
power: boolean,
moisture: number,
temperature: number,
humidity: number
}
const dataContainer = document.getElementById('data-container') as HTMLDivElement
const config = { const config = {
iceServers: [ iceServers: [
{ {
@ -36,7 +44,11 @@ dataChannel.onopen = () => {
}; };
dataChannel.onmessage = (event) => { dataChannel.onmessage = (event) => {
console.log("📦 Client received message:", event.data); // console.log("📦 Client received message:", event.data);
const json = JSON.parse(event.data) ;
dataContainer.innerHTML = Object.entries(json).map(([k,v])=>`<p>${k}:${v}</p>`).join('')
}; };
dataChannel.onclose = () => { dataChannel.onclose = () => {