Working API communication with the server
This commit is contained in:
parent
36c6cf5bda
commit
3450695885
@ -10,9 +10,11 @@
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"axios": "^1.6.7",
|
||||
"bootstrap-icons": "^1.11.3",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0"
|
||||
"react-dom": "^18.2.0",
|
||||
"socket.io-client": "^4.7.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/react": "^18.2.56",
|
||||
|
@ -4,7 +4,7 @@ import BackroundImg from "../assets/img/background.png";
|
||||
export default function MainBody({ children }: { children?: ReactNode }) {
|
||||
return (
|
||||
<div
|
||||
className="bg-background text-white bg-repeat-y relative"
|
||||
className="bg-background text-white bg-repeat-y bg-cover relative"
|
||||
style={{
|
||||
backgroundImage: `url(${BackroundImg})`
|
||||
}}
|
||||
|
@ -1,11 +1,46 @@
|
||||
import { ChangeEvent, Ref, useEffect } from "react";
|
||||
import PinBox from "../forms/PinBox";
|
||||
import { useLed } from "../../hooks";
|
||||
import ControlSection from "../ControlSection";
|
||||
import { Ref } from "react";
|
||||
import { PinState } from "../../types/board";
|
||||
import { PatchLed } from "../../controllers/BoardController";
|
||||
|
||||
function LedItem ({ led, index }: { led: PinState, index: number }) {
|
||||
const { removeLed, setLed, setLedPin } = useLed();
|
||||
|
||||
const handleChange = (e: ChangeEvent<HTMLInputElement | null>) => {
|
||||
const pin = e.target?.value;
|
||||
setLedPin(index, pin);
|
||||
}
|
||||
|
||||
const toggleLed = () => {
|
||||
setLed(led.pin, !led.state);
|
||||
}
|
||||
|
||||
const handleRemove = () => {
|
||||
removeLed(index);
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
const pin: number = typeof led.pin == "string" ? Number.parseInt(led.pin) : led.pin;
|
||||
PatchLed(pin, led.state);
|
||||
}, [led.state]);
|
||||
|
||||
return (
|
||||
<PinBox.Toggle
|
||||
className="w-36 animate-fade-in"
|
||||
minusBtn={true}
|
||||
value={led.pin}
|
||||
state={led.state}
|
||||
onValueChange={handleChange}
|
||||
onStateChange={toggleLed}
|
||||
onDelete={handleRemove}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function ControlLED ({ refto }: { refto?: Ref<HTMLDivElement> }) {
|
||||
const { addLed, leds, removeLed, setLed, setLedPin } = useLed();
|
||||
const { addLed, leds } = useLed();
|
||||
|
||||
const handleAdd = (): void => {
|
||||
let anopin = 13;
|
||||
@ -28,23 +63,10 @@ function ControlLED ({ refto }: { refto?: Ref<HTMLDivElement> }) {
|
||||
refto={refto}
|
||||
stack={(<>
|
||||
{leds.map((led, i) => (
|
||||
<PinBox.Toggle
|
||||
className="w-36 animate-fade-in"
|
||||
<LedItem
|
||||
led={led}
|
||||
index={i}
|
||||
key={i}
|
||||
minusBtn={true}
|
||||
value={led.pin}
|
||||
state={led.state}
|
||||
onValueChange={(e) => {
|
||||
const pin = e.target.value;
|
||||
setLedPin(i, pin);
|
||||
}}
|
||||
onStateChange={() => {
|
||||
const state = !led.state;
|
||||
setLed(led.pin, state);
|
||||
}}
|
||||
onDelete={() => {
|
||||
removeLed(i);
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
{leds.length < 14 && <PinBox.Add
|
||||
|
@ -1,14 +1,15 @@
|
||||
import { ChangeEvent, MouseEventHandler, Ref, useState } from "react";
|
||||
import { ChangeEvent, MouseEventHandler, Ref, useEffect, useState } from "react";
|
||||
import { usePhotoresistor } from "../../hooks";
|
||||
import { DynamicPinState } from "../../types/board";
|
||||
import CircleResistance from "../shapes/CircleResistance";
|
||||
import TwoRowTab from "../info/TwoRowTab";
|
||||
import EvoInput from "../forms/EvoInput";
|
||||
import Button from "../forms/Button";
|
||||
import { io } from "../../socket/socket.io";
|
||||
|
||||
|
||||
function Card ({ index, resistor }: { index: number, resistor: DynamicPinState }) {
|
||||
const { setResistorPin, removeResistor } = usePhotoresistor();
|
||||
const { setResistorPin, setResistance, removeResistor } = usePhotoresistor();
|
||||
|
||||
const [isListen, setListen] = useState<boolean>(false);
|
||||
|
||||
@ -27,6 +28,26 @@ function Card ({ index, resistor }: { index: number, resistor: DynamicPinState }
|
||||
removeResistor(index);
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
const pin = typeof resistor.pin == "string" && resistor.pin[0] == "A" ?
|
||||
resistor.pin[1] : resistor.pin;
|
||||
|
||||
if (isListen) {
|
||||
io.emit("set-photoresistor", pin);
|
||||
|
||||
const handler = (value: string) => {
|
||||
const res: number = Number.parseInt(value);
|
||||
setResistance(resistor.pin, res);
|
||||
}
|
||||
|
||||
io.on("photoresistor", handler);
|
||||
|
||||
return () => {
|
||||
io.off("photoresistor", handler);
|
||||
}
|
||||
}
|
||||
}, [io, isListen]);
|
||||
|
||||
return (
|
||||
<div className="border border-border bg-secondary col-span-2 rounded-lg p-6 animate-size-fade-in">
|
||||
<div className="flex justify-items-end">
|
||||
@ -36,7 +57,7 @@ function Card ({ index, resistor }: { index: number, resistor: DynamicPinState }
|
||||
</div>
|
||||
<div className="h-52 flex items-center justify-center">
|
||||
<CircleResistance
|
||||
resistance={0}
|
||||
intensity={intensity}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex flex-col mt-3 gap-3">
|
||||
@ -98,7 +119,7 @@ function ControlPhotoresistor ({ refto }: { refto?: Ref<HTMLDivElement> }) {
|
||||
Photoresistor
|
||||
</h2>
|
||||
<div className="grid grid-cols-8 mb-8">
|
||||
<p className="col-span-6">Also known as LDR (Light Dependent Resistor), it is an electronic component whose resistance changes based on the intensity of light it receives. The higher the light intensity, the lower the resistance, When exposed to intense light, a photoresistor experiences a decrease in resistance due to photoconduction. The molecules in the photoresistor material become more active and allow electric current to flow through the material more easily.</p>
|
||||
<p className="col-span-6">Also known as LDR {"("}Light Dependent Resistor{")"}, it is an electronic component whose resistance changes based on the intensity of light it receives. The higher the light intensity, the lower the resistance, When exposed to intense light, a photoresistor experiences a decrease in resistance due to photoconduction. The molecules in the photoresistor material become more active and allow electric current to flow through the material more easily.</p>
|
||||
</div>
|
||||
<div className={`grid grid-cols-8 gap-6`}>
|
||||
{resistors.map((resistor, i) => (
|
||||
|
@ -1,6 +1,7 @@
|
||||
import PinBox from "../forms/PinBox";
|
||||
import ControlSection from "../ControlSection";
|
||||
import { Ref } from "react";
|
||||
import { PatchPiezo } from "../../controllers/BoardController";
|
||||
import { ChangeEvent, Ref, useEffect, useState } from "react";
|
||||
import { usePiezo } from "../../hooks";
|
||||
import { DynamicPinState } from "../../types/board";
|
||||
import EvoInput from "../forms/EvoInput";
|
||||
@ -9,31 +10,48 @@ import Button from "../forms/Button";
|
||||
function PiezoItem ({ piezo, index }: { piezo: DynamicPinState, index: number }) {
|
||||
const { setFrequency, setPiezoPin, removePiezo } = usePiezo();
|
||||
|
||||
const [freq, setFreq] = useState<number | string>(piezo.state);
|
||||
|
||||
const handlePinChange = (e: ChangeEvent<HTMLInputElement | null>) => {
|
||||
const pin = e.target?.value;
|
||||
setPiezoPin(index, pin);
|
||||
}
|
||||
|
||||
const handleFreqChange = (e: ChangeEvent<HTMLInputElement | null>) => {
|
||||
setFreq(e.target.value);
|
||||
}
|
||||
|
||||
const handleDelete = () => {
|
||||
removePiezo(index);
|
||||
}
|
||||
|
||||
const handlePatch = () => {
|
||||
const pin: number = typeof piezo.pin == "string" ? Number.parseInt(piezo.pin) : piezo.pin;
|
||||
PatchPiezo(pin, piezo.state);
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
const f: number = typeof freq == "string" ? Number.parseInt(freq) : freq;
|
||||
if (!Number.isNaN(freq)) setFrequency(index, f);
|
||||
}, [freq])
|
||||
|
||||
return (
|
||||
<div className="flex flex-col gap-3">
|
||||
<PinBox
|
||||
className="w-36 animate-fade-in"
|
||||
minusBtn={true}
|
||||
value={piezo.pin}
|
||||
onValueChange={(e) => {
|
||||
const pin = e.target.value;
|
||||
setPiezoPin(index, pin);
|
||||
}}
|
||||
onDelete={() => {
|
||||
removePiezo(index);
|
||||
}}
|
||||
onValueChange={handlePinChange}
|
||||
onDelete={handleDelete}
|
||||
/>
|
||||
<EvoInput
|
||||
className="w-36 h-11"
|
||||
name="Frequency"
|
||||
type="number"
|
||||
value={piezo.state.toString()}
|
||||
onChange={(e) => {
|
||||
const freq: number = Number.parseInt(e.target.value);
|
||||
if (!Number.isNaN(freq)) setFrequency(piezo.pin, freq);
|
||||
}}
|
||||
onChange={handleFreqChange}
|
||||
/>
|
||||
<Button.Primary className="text-sm !py-0 h-11">Play</Button.Primary>
|
||||
<Button.Primary onClick={handlePatch} className="text-sm !py-0 h-11">Play</Button.Primary>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
import { PatchRgbLed } from "../../controllers/BoardController";
|
||||
import { useRgbLed } from "../../hooks";
|
||||
import { ChannelPinState, PinState } from "../../types/board";
|
||||
import EvoInput from "../forms/EvoInput";
|
||||
@ -5,34 +6,51 @@ import Switch from "../forms/Switch";
|
||||
import { MouseEventHandler, Ref, useEffect, useState } from "react";
|
||||
|
||||
interface HorizontalBarProps {
|
||||
pinState: ChannelPinState;
|
||||
onUpdate?: (pin: ChannelPinState) => void;
|
||||
onDelete?: () => void
|
||||
rgbLed: ChannelPinState;
|
||||
index: number;
|
||||
}
|
||||
|
||||
function HorizontalBar ({ pinState, onUpdate, onDelete }: HorizontalBarProps) {
|
||||
function HorizontalBar ({ rgbLed, index }: HorizontalBarProps) {
|
||||
const { removeLed, setLed } = useRgbLed();
|
||||
|
||||
const handleUpdate = (led: ChannelPinState) => {
|
||||
setLed(index, led);
|
||||
}
|
||||
|
||||
const handleRemove = () => {
|
||||
removeLed(index);
|
||||
}
|
||||
|
||||
const [red, setRed] = useState<PinState>({
|
||||
pin: pinState.red.pin.toString(),
|
||||
state: pinState.red.state
|
||||
pin: rgbLed.red.pin.toString(),
|
||||
state: rgbLed.red.state
|
||||
});
|
||||
|
||||
const [green, setGreen] = useState<PinState>({
|
||||
pin: pinState.green.pin.toString(),
|
||||
state: pinState.green.state
|
||||
pin: rgbLed.green.pin.toString(),
|
||||
state: rgbLed.green.state
|
||||
});
|
||||
|
||||
const [blue, setBlue] = useState<PinState>({
|
||||
pin: pinState.blue.pin.toString(),
|
||||
state: pinState.blue.state
|
||||
pin: rgbLed.blue.pin.toString(),
|
||||
state: rgbLed.blue.state
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (onUpdate) onUpdate({red, green, blue});
|
||||
}, [red, green, blue])
|
||||
handleUpdate({red, green, blue});
|
||||
}, [red, green, blue]);
|
||||
|
||||
useEffect(() => {
|
||||
PatchRgbLed(rgbLed);
|
||||
}, [
|
||||
rgbLed.red.state,
|
||||
rgbLed.green.state,
|
||||
rgbLed.blue.state
|
||||
]);
|
||||
|
||||
return (
|
||||
<div className="flex flex-col col-span-3 gap-2 animate-fade-in font-roboto-mono">
|
||||
<button className="ms-auto bg-finn hover:bg-secondary transition border border-border rounded-lg px-5" onClick={onDelete}>
|
||||
<button className="ms-auto bg-finn hover:bg-secondary transition border border-border rounded-lg px-5" onClick={handleRemove}>
|
||||
<i className="bi bi-dash text-xl"></i>
|
||||
</button>
|
||||
<div className="bg-secondary animate-size-in rounded-lg border border-border p-4 flex gap-3">
|
||||
@ -122,7 +140,7 @@ function HorizontalBarPlus ({ onClick }: { onClick?: MouseEventHandler<HTMLButto
|
||||
}
|
||||
|
||||
function ControlRgbLed ({ refto }: { refto?: Ref<HTMLDivElement> }) {
|
||||
const { addLed, rgbLed, removeLed, setLed } = useRgbLed();
|
||||
const { addLed, rgbLed } = useRgbLed();
|
||||
|
||||
const handleAdd = (): void => {
|
||||
addLed({
|
||||
@ -155,13 +173,8 @@ function ControlRgbLed ({ refto }: { refto?: Ref<HTMLDivElement> }) {
|
||||
{rgbLed.map((led, i) => (
|
||||
<HorizontalBar
|
||||
key={i}
|
||||
pinState={led}
|
||||
onUpdate={(newLed) => {
|
||||
setLed(i, newLed);
|
||||
}}
|
||||
onDelete={() => {
|
||||
removeLed(i);
|
||||
}}
|
||||
index={i}
|
||||
rgbLed={led}
|
||||
/>
|
||||
))}
|
||||
{rgbLed.length < 5 && <HorizontalBarPlus
|
||||
|
@ -4,6 +4,7 @@ import { DynamicPinState } from "../../types/board";
|
||||
import EvoInput from "../forms/EvoInput";
|
||||
import Button from "../forms/Button";
|
||||
import { Slider } from "../forms/Slider";
|
||||
import { PatchServo } from "../../controllers/BoardController";
|
||||
|
||||
|
||||
function Bar ({ index, servo }: { index: number, servo: DynamicPinState }) {
|
||||
@ -17,6 +18,10 @@ function Bar ({ index, servo }: { index: number, servo: DynamicPinState }) {
|
||||
setDegree(servo.pin, deg);
|
||||
}, [percentage]);
|
||||
|
||||
useEffect(() => {
|
||||
if (isListen) PatchServo(servo.pin, servo.state);
|
||||
}, [isListen, servo.state])
|
||||
|
||||
const toggleListen = () => {
|
||||
setListen(!isListen);
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ interface CircleResistanceProps {
|
||||
width?: number;
|
||||
height?: number;
|
||||
blur?: number;
|
||||
resistance?: number;
|
||||
intensity?: number;
|
||||
}
|
||||
|
||||
export default function CircleResistance({
|
||||
@ -11,7 +11,7 @@ export default function CircleResistance({
|
||||
width,
|
||||
height,
|
||||
blur,
|
||||
resistance,
|
||||
intensity,
|
||||
}: CircleResistanceProps) {
|
||||
return (
|
||||
<div
|
||||
@ -24,14 +24,15 @@ export default function CircleResistance({
|
||||
}}
|
||||
>
|
||||
<div
|
||||
className="transition-opacity duration-75"
|
||||
style={{
|
||||
backgroundColor: "white",
|
||||
borderRadius: 999,
|
||||
width: width || 122,
|
||||
height: height || 122,
|
||||
filter: `blur(${blur || 12}px)`,
|
||||
boxShadow: '0 0 52 22 #FF2929',
|
||||
opacity: resistance ? resistance/1023*100 : 0
|
||||
boxShadow: '0 0 52px 22px #FF2929',
|
||||
opacity: intensity+"%"
|
||||
}}
|
||||
></div>
|
||||
</div>
|
||||
|
@ -43,12 +43,12 @@ const INIT_VALUES: ControllerContextProps = {
|
||||
piezo: [
|
||||
{
|
||||
pin: 6,
|
||||
state: 127
|
||||
state: 262
|
||||
}
|
||||
],
|
||||
motoServo: [
|
||||
{
|
||||
pin: "A0",
|
||||
pin: "9",
|
||||
state: 0
|
||||
}
|
||||
],
|
||||
|
51
src/controllers/BoardController.tsx
Normal file
51
src/controllers/BoardController.tsx
Normal file
@ -0,0 +1,51 @@
|
||||
import axios from "axios";
|
||||
import { ChannelPinState } from "../types/board";
|
||||
import { io } from "../socket/socket.io";
|
||||
|
||||
const url = "http://localhost:3000/api-arduino";
|
||||
|
||||
export async function PatchLed (pin: number, state: boolean) {
|
||||
const act = state == true ? 'on' : 'off';
|
||||
|
||||
const res = await axios.patch(`${url}/led/${pin}/${act}`);
|
||||
const data = res.data;
|
||||
|
||||
console.log("LED Response: ", data);
|
||||
}
|
||||
|
||||
export async function PatchRgbLed (state: ChannelPinState) {
|
||||
const { red, green, blue } = state;
|
||||
const body = {
|
||||
r: {
|
||||
pin: red.pin,
|
||||
value: red.state
|
||||
},
|
||||
g: {
|
||||
pin: green.pin,
|
||||
value: green.state
|
||||
},
|
||||
b: {
|
||||
pin: blue.pin,
|
||||
value: blue.state
|
||||
}
|
||||
}
|
||||
const res = await axios.patch(`${url}/rgb-led`, body, {
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
});
|
||||
const data = res.data;
|
||||
|
||||
console.log("RGB LED Response: ", data);
|
||||
}
|
||||
|
||||
export async function PatchPiezo (pin: number, freq: number) {
|
||||
const res = await axios.patch(`${url}/piezo/${pin}/${freq}`);
|
||||
const data = res.data;
|
||||
|
||||
console.log("Piezo Response: ", data);
|
||||
}
|
||||
|
||||
export async function PatchServo(pin: string | number, value: number) {
|
||||
io.emit("servo", pin, value);
|
||||
}
|
@ -86,7 +86,7 @@
|
||||
|
||||
|
||||
.btn {
|
||||
@apply px-5 py-4 transition font-roboto-mono rounded-lg
|
||||
@apply px-5 py-4 transition font-roboto-mono rounded-lg transition-[transform] duration-75 scale-100 active:scale-90;
|
||||
}
|
||||
|
||||
|
||||
|
@ -15,8 +15,7 @@ export function useLed () {
|
||||
}
|
||||
|
||||
const addLed = (pin: number | string, state?: boolean) => {
|
||||
const newLed = [...leds, { pin, state: state || false }];
|
||||
setLeds!(newLed);
|
||||
setLeds!(led => [...led, { pin, state: state || false }]);
|
||||
}
|
||||
|
||||
const removeLed = (index: number) => {
|
||||
@ -100,12 +99,11 @@ export function usePiezo () {
|
||||
setPiezo!(newPiezo);
|
||||
}
|
||||
|
||||
const setFrequency = (pin: number | string, state: number) => {
|
||||
const newPiezo = piezo.map(piezo => {
|
||||
if (piezo.pin == pin) return { pin, state };
|
||||
const setFrequency = (index: number, state: number) => {
|
||||
setPiezo!(piezos => piezos.map((piezo, i) => {
|
||||
if (i == index) return { pin: piezo.pin, state: state };
|
||||
return piezo;
|
||||
})
|
||||
setPiezo!(newPiezo);
|
||||
}));
|
||||
}
|
||||
|
||||
const setPiezoPin = (index: number | string, newPin: number | string) => {
|
||||
@ -175,6 +173,14 @@ export function usePhotoresistor () {
|
||||
setPhotoresistor!(newPesistor);
|
||||
}
|
||||
|
||||
const setResistance = (pin: number | string, state: number) => {
|
||||
const resistor = photoresistor.map(resist => {
|
||||
if (resist.pin == pin) return { pin: resist.pin, state };
|
||||
return resist;
|
||||
})
|
||||
setPhotoresistor!(resistor);
|
||||
}
|
||||
|
||||
const setResistorPin = (index: number, newPin: number | string) => {
|
||||
const newPesistor = photoresistor.map((resist, i) => {
|
||||
if (i == index) return { pin: newPin, state: resist.state };
|
||||
@ -183,5 +189,5 @@ export function usePhotoresistor () {
|
||||
setPhotoresistor!(newPesistor);
|
||||
}
|
||||
|
||||
return { photoresistor, getResistor, addResistor, removeResistor, setResistorPin };
|
||||
return { photoresistor, getResistor, addResistor, removeResistor, setResistance, setResistorPin };
|
||||
}
|
||||
|
3
src/socket/socket.io.ts
Normal file
3
src/socket/socket.io.ts
Normal file
@ -0,0 +1,3 @@
|
||||
import { connect } from "socket.io-client";
|
||||
|
||||
export const io = connect("http://localhost:3000");
|
Loading…
x
Reference in New Issue
Block a user