Dev prototype #1

Merged
david merged 7 commits from dev into main 2025-04-24 11:34:49 -07:00
6 changed files with 127 additions and 12 deletions
Showing only changes of commit e6b72c597a - Show all commits

View File

@ -1,6 +1,7 @@
import * as http from "http"; import * as http from "http";
import * as fs from "fs"; import * as fs from "fs";
import * as path from "path"; import * as path from "path";
import { ISensors } from "./io";
export default class HttpServer { export default class HttpServer {
@ -10,7 +11,7 @@ export default class HttpServer {
private root: string; private root: string;
// public constructor(port: number, root: string, tune: (ch: string, adp?: number) => void, getChannels: ()=>string[], getSignal: (adapter:number)=>object) { // public constructor(port: number, root: string, tune: (ch: string, adp?: number) => void, getChannels: ()=>string[], getSignal: (adapter:number)=>object) {
public constructor(port: number, root: string) { public constructor(port: number, root: string, getSensors: ()=>ISensors, setPower: (power: boolean) => void) {
this.port = port; this.port = port;
this.root = root; this.root = root;
this.httpServer = http.createServer((req, res) => { this.httpServer = http.createServer((req, res) => {
@ -25,8 +26,8 @@ export default class HttpServer {
switch (req.method) { switch (req.method) {
case "GET": case "GET":
switch (api) { switch (api) {
case "list": case "sensors":
// body = JSON.stringify(getChannels()); body = JSON.stringify(getSensors());
status = 200; status = 200;
break; break;
case "signal": case "signal":
@ -39,7 +40,7 @@ export default class HttpServer {
break; break;
case "PUT": case "PUT":
switch (api) { switch (api) {
case "tune": case "power":
const channel = decodeURIComponent(query[3]); const channel = decodeURIComponent(query[3]);
const adapter = parseInt(url.searchParams.get('adapter')); const adapter = parseInt(url.searchParams.get('adapter'));
// tune(channel, adapter); // tune(channel, adapter);

50
src/io.ts Normal file
View File

@ -0,0 +1,50 @@
import Serial from "./serial";
import * as onoff from 'onoff'
const ON = onoff.Gpio.HIGH;
const OFF = onoff.Gpio.LOW;
export interface ISensors {
temperature: number;
power: boolean;
moisture: number;
humidity: number
}
export default class IO {
private temp: number
private serial: Serial;
// private power: boolean;
private gpio: onoff.Gpio
public constructor(POWER_GPIO = 17) {
this.serial = new Serial();
this.gpio = new onoff.Gpio(POWER_GPIO, 'out');
}
public getPower() {
return this.gpio.readSync()
}
public setPower(power: boolean) {
this.gpio.writeSync(power ? ON : OFF);
}
public togglePower() {
const cur: onoff.BinaryValue = this.getPower() ;
this.gpio.writeSync(cur ? OFF : ON);
}
public getSensors (): ISensors {
return {
power: this.getPower() ? true : false,
moisture: 0,
temperature: 0,
humidity: 0
}
}
public getMoisture() {
return this.serial.getMoisture()
}
}

34
src/serial.ts Normal file
View File

@ -0,0 +1,34 @@
import * as serialport from 'serialport';
// interface ISerial {
// moisture: number;
// parser: serialport.ReadlineParser
// }
export default class Serial {
private moisture: number;
public constructor(path = '/dev/ttyUSB0', baudRate = 9600, delimiter = '\n') {
const port = new serialport.SerialPort({ path, baudRate });
const readline = new serialport.ReadlineParser({ delimiter });
const parser = port.pipe(readline);
parser.on('data', line => {
const moisture = parseInt(line.trim(), 10);
if (!isNaN(moisture)) {
this.moisture = moisture
}
});
port.on('error', err => {
console.error('Serial Error:', err.message);
});
}
public getMoisture() {
return this.moisture;
}
}

View File

@ -1,4 +1,5 @@
import HttpServer from './http'; import HttpServer from './http';
import IO from './io';
import VideoSocket from './ws'; import VideoSocket from './ws';
const HTTP_PORT = process.env.HTTP_PORT ? parseInt(process.env.HTTP_PORT, 10) : 8080; const HTTP_PORT = process.env.HTTP_PORT ? parseInt(process.env.HTTP_PORT, 10) : 8080;
@ -24,26 +25,44 @@ const TV_DEV_0 = process.env.TV_DEV_0 ?? '/dev/video0'
// const getSignal = (adapter: number) => // const getSignal = (adapter: number) =>
// zap.getSignal(adapter) // zap.getSignal(adapter)
const httpServer = new HttpServer(HTTP_PORT, STATIC_ROOT); const io = new IO();
const httpServer = new HttpServer(HTTP_PORT, STATIC_ROOT, io.getSensors, io.setPower);
const videoSocket = new VideoSocket(WS_PORT, TV_DEV_0); const videoSocket = new VideoSocket(WS_PORT, TV_DEV_0);
httpServer.start(); httpServer.start();
process.stdin.setEncoding("utf8"); process.stdin.setEncoding("utf8");
process.stdin.resume(); process.stdin.resume();
console.log("Menu:"); console.log("Menu:\n1) Power off\n2)Power on\n3) Power flop\n4)Read moisture");
process.stdin.on("data", async (data: string) => { process.stdin.on("data", async (data: string) => {
const input = data.trim(); const input = data.trim();
console.log(`Received: "${input}"`); console.log(`Received: "${input}"`);
// await zap.zapTo(input).then((zap: IZap) => { const val = parseInt(input);
// console.log(`Tuned ${zap.adapter} to ${zap.channel}`) switch(val) {
case 0:
// }).catch((err: Error) => { break;
// console.error(err.message); case 1:
// }); io.setPower(false);
break;
case 2:
io.setPower(true);
break;
case 3:
io.setPower(io.getPower()? true:false)
break;
case 4:
console.log(io.getMoisture());
default:
console.log("No option for "+input)
}
}); });

View File

@ -18,12 +18,14 @@
<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>
<button onclick="poll()">Poll</button>
</main> </main>
</div> </div>
<script src="js/video.js"></script> <script src="js/video.js"></script>
<script src="js/api.js"></script>
</body> </body>
</html> </html>

9
src/static/js/api.ts Normal file
View File

@ -0,0 +1,9 @@
const getSensors = () =>{
}
const poll = () =>{
fetch("/api/sensors").then(r=>r.json()).then(data =>{
console.log("data ",data)
})
}