From e10a4929107f61cbad01683d5866611c5cdd6fef Mon Sep 17 00:00:00 2001 From: David Westgate Date: Sun, 20 Apr 2025 03:48:53 +0100 Subject: [PATCH] seperate lights/heat --- package.json | 8 +++- src/io.ts | 87 +++++++++++++++++++++++------------------- src/serial.ts | 14 ++++--- src/server.ts | 14 ++++--- src/static/index.html | 8 +++- src/static/js/video.ts | 20 ++++++++-- 6 files changed, 94 insertions(+), 57 deletions(-) diff --git a/package.json b/package.json index f6c819c..969a0cf 100644 --- a/package.json +++ b/package.json @@ -1,9 +1,12 @@ { "dependencies": { "@roamhq/wrtc": "0.8.0", + "node-dht-sensor": "^0.4.5", "node-pre-gyp": "^0.17.0", - "ws": "^8.18.0", - "sass": "1.86.3" + "pigpio": "^3.3.1", + "sass": "1.86.3", + "serialport": "^13.0.0", + "ws": "^8.18.0" }, "scripts": { "build:scss": "npx sass src/static/css:dist/static/css", @@ -16,6 +19,7 @@ }, "devDependencies": { "@types/node": "^22.10.2", + "@types/node-dht-sensor": "^0.4.2", "@types/ws": "^8.5.13", "ts-node": "^10.9.2", "typescript": "^5.8.2" diff --git a/src/io.ts b/src/io.ts index 355837b..308504c 100644 --- a/src/io.ts +++ b/src/io.ts @@ -1,69 +1,78 @@ import Serial from "./serial"; import * as pigpio from 'pigpio'; +import * as dht from 'node-dht-sensor'; type ONOFF = 0 | 1; const ON: ONOFF = 0 -const OFF: ONOFF = 1 +const OFF: ONOFF = 1 export interface ISensors { temperature: number; - power: boolean; - moisture: number; + lights: boolean; + heat: boolean + moisture0: number; + moisture1: number; humidity: number; } -export default class IO implements ISensors { - temperature: number; - moisture: number; - humidity: number; - gpio: pigpio.Gpio +export default class IO { + gpioLights: pigpio.Gpio + gpioHeat: pigpio.Gpio serial: Serial; - power: boolean; - getMoisture : ()=>number; + lights: boolean; + 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() this.getMoisture = serial.getMoisture.bind(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 - this.temperature = 0; - // this.serial.getMoisture.bind(this) + const readLights = new pigpio.Gpio(LIGHTS_GPIO, { mode: pigpio.Gpio.INPUT }); + this.lights = readLights.digitalRead() == ON ? true : false + 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) { - // Set the GPIO pin to high (1) or low (0) - 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); - } + private round = (n) => + (n * 100) / 100 public getSensors(): ISensors { - // console.log("serial ", ) + const { temperature, humidity } = dht.read(22, 27) + const { moisture0, moisture1 } = this.getMoisture() return { - power: this.power, - moisture: this.getMoisture(), - temperature: this.temperature, - humidity: this.humidity + lights: this.lights, + heat: this.heat, + moisture0: moisture0, + moisture1: moisture1, + temperature: this.round(temperature), + humidity: this.round(humidity) } } - - } diff --git a/src/serial.ts b/src/serial.ts index 67a1594..3a564fa 100644 --- a/src/serial.ts +++ b/src/serial.ts @@ -14,25 +14,29 @@ export default class Serial { const readline = new serialport.ReadlineParser({ delimiter }); const parser = port.pipe(readline); parser.on('data', line => { - // console.log("data line ", line) const data = JSON.parse(line) const moisture0 = parseInt(data['A0'], 10); const moisture1 = parseInt(data['A1'], 10); if (!isNaN(moisture0) && !isNaN(moisture1)) { - // console.log("m ", this.moisture) this.moisture0 = moisture0; this.moisture1 = moisture1; } - else{ - console.log("data ",data) + else { + console.error("Error reading analog data") } }); port.on('error', err => { 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() { - return this.moisture0; + return { moisture0: this.scale(this.moisture0), moisture1: this.scale(this.moisture1) }; } diff --git a/src/server.ts b/src/server.ts index baac545..3275c97 100644 --- a/src/server.ts +++ b/src/server.ts @@ -42,7 +42,7 @@ httpServer.start(); process.stdin.setEncoding("utf8"); 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) => { const input = data.trim(); @@ -53,16 +53,20 @@ process.stdin.on("data", async (data: string) => { break; case 1: - io.setPower(false); + io.setPower(false,17); break; case 2: - io.setPower(true); + io.setPower(true,17); break; case 3: - io.togglePower(); + io.setPower(false,22); break; case 4: - + io.setPower(true,22); + break; + + + case 5: console.log("a ", getSensors()) break; default: diff --git a/src/static/index.html b/src/static/index.html index 7ceffb1..032a7b6 100644 --- a/src/static/index.html +++ b/src/static/index.html @@ -18,8 +18,12 @@
-

- +
+ +
diff --git a/src/static/js/video.ts b/src/static/js/video.ts index b046387..d453ae2 100644 --- a/src/static/js/video.ts +++ b/src/static/js/video.ts @@ -2,6 +2,14 @@ const isSecure = window.location.protocol === 'https:'; const host = window.location.hostname; const ws0builder = isSecure ? `wss://${host}/ws3` : `ws://${host}:3003`; 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 = { iceServers: [ { @@ -11,7 +19,7 @@ const config = { } ] }; -const pc0 = new RTCPeerConnection(isSecure ? config: {}); +const pc0 = new RTCPeerConnection(isSecure ? config : {}); const video0 = document.getElementById('video0') as HTMLVideoElement; @@ -32,15 +40,19 @@ const dataChannel = pc0.createDataChannel('sensors'); console.log("📡 Data channel created by client"); dataChannel.onopen = () => { - console.log('📬 Client: Data channel opened'); + console.log('📬 Client: Data channel opened'); }; 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])=>`

${k}:${v}

`).join('') + }; dataChannel.onclose = () => { - console.log("📴 Client: Data channel closed"); + console.log("📴 Client: Data channel closed"); }; ws0.onopen = async () => {