seperate lights/heat
This commit is contained in:
parent
22aeed01be
commit
e10a492910
@ -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"
|
||||||
|
87
src/io.ts
87
src/io.ts
@ -1,69 +1,78 @@
|
|||||||
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
|
||||||
const OFF: ONOFF = 1
|
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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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) };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -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:
|
||||||
|
@ -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>
|
||||||
|
@ -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: [
|
||||||
{
|
{
|
||||||
@ -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;
|
const video0 = document.getElementById('video0') as HTMLVideoElement;
|
||||||
|
|
||||||
|
|
||||||
@ -32,15 +40,19 @@ const dataChannel = pc0.createDataChannel('sensors');
|
|||||||
console.log("📡 Data channel created by client");
|
console.log("📡 Data channel created by client");
|
||||||
|
|
||||||
dataChannel.onopen = () => {
|
dataChannel.onopen = () => {
|
||||||
console.log('📬 Client: Data channel opened');
|
console.log('📬 Client: Data channel opened');
|
||||||
};
|
};
|
||||||
|
|
||||||
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 = () => {
|
||||||
console.log("📴 Client: Data channel closed");
|
console.log("📴 Client: Data channel closed");
|
||||||
};
|
};
|
||||||
|
|
||||||
ws0.onopen = async () => {
|
ws0.onopen = async () => {
|
||||||
|
Loading…
Reference in New Issue
Block a user