First implementation of redux connection system
This commit is contained in:
parent
751c981daf
commit
c31f3b19ac
6 changed files with 132 additions and 37 deletions
|
@ -1,8 +1,10 @@
|
||||||
import React, { useEffect, useState } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
import { createGlobalStyle } from "styled-components";
|
import { createGlobalStyle } from "styled-components";
|
||||||
import SerialPort from "serialport";
|
import { useDispatch, useSelector } from "react-redux";
|
||||||
|
import { RootState } from "typesafe-actions";
|
||||||
import Knob from "./Components/Knob";
|
import Knob from "./Components/Knob";
|
||||||
import { port, parser } from "./SerialConnection";
|
import { connect, disconnect } from "./redux/actions/asyncSerialConnectionActions";
|
||||||
|
import { setSerialPort } from "./redux/actions/serialConnectionActions";
|
||||||
|
|
||||||
const GlobalStyle = createGlobalStyle`
|
const GlobalStyle = createGlobalStyle`
|
||||||
html {
|
html {
|
||||||
|
@ -18,6 +20,9 @@ const GlobalStyle = createGlobalStyle`
|
||||||
|
|
||||||
const App = () => {
|
const App = () => {
|
||||||
const [status, setStatus] = useState(0);
|
const [status, setStatus] = useState(0);
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
const serialConnection = useSelector<RootState, RootState["serialConnection"]>((state) => state.serialConnection);
|
||||||
|
|
||||||
const SerialDataListener = (data: string) => {
|
const SerialDataListener = (data: string) => {
|
||||||
const parsedData = data.split(",");
|
const parsedData = data.split(",");
|
||||||
console.log(parsedData);
|
console.log(parsedData);
|
||||||
|
@ -25,24 +30,34 @@ const App = () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
parser.on("data", SerialDataListener);
|
if (serialConnection.portController !== null) {
|
||||||
port.open();
|
serialConnection.portController.parser.on("data", SerialDataListener);
|
||||||
|
}
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
parser.removeListener("data", SerialDataListener);
|
if (serialConnection.portController !== null) {
|
||||||
port.close();
|
serialConnection.portController.parser.removeListener("data", SerialDataListener);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}, []);
|
}, [serialConnection]);
|
||||||
|
|
||||||
const sendIncreaseHandler = () => {
|
const sendIncreaseHandler = () => {
|
||||||
setStatus(status + 1);
|
if (serialConnection.portController !== null && serialConnection.portController.port !== null) {
|
||||||
port.write("2i");
|
setStatus(status + 1);
|
||||||
|
serialConnection.portController.port.write("2i");
|
||||||
|
}
|
||||||
};
|
};
|
||||||
const sendDecreaseHandler = () => {
|
const sendDecreaseHandler = () => {
|
||||||
setStatus(status - 1);
|
if (serialConnection.portController !== null && serialConnection.portController.port !== null) {
|
||||||
port.write("2d");
|
setStatus(status - 1);
|
||||||
|
serialConnection.portController.port.write("2d");
|
||||||
|
}
|
||||||
};
|
};
|
||||||
const sendToggleHandler = () => {
|
const sendToggleHandler = () => {
|
||||||
port.write("2t");
|
if (serialConnection.portController !== null && serialConnection.portController.port !== null) {
|
||||||
|
setStatus(status - 1);
|
||||||
|
serialConnection.portController.port.write("2t");
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -57,29 +72,19 @@ const App = () => {
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
port.open();
|
dispatch(setSerialPort("COM5"));
|
||||||
|
dispatch(connect());
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
open
|
connect
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
port.close();
|
dispatch(disconnect());
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
close
|
disconnect
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
onClick={() => {
|
|
||||||
const list = SerialPort.list();
|
|
||||||
list.then((arg) => {
|
|
||||||
console.log(arg);
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
list
|
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,10 +1,51 @@
|
||||||
import SerialPort, { parsers } from "serialport";
|
import SerialPort, { parsers } from "serialport";
|
||||||
|
|
||||||
const port = new SerialPort("COM5", {
|
class PortController {
|
||||||
baudRate: 9600,
|
path: null | string;
|
||||||
autoOpen: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
const parser = port.pipe(new parsers.Readline({ delimiter: "\r\n" }));
|
port: null | SerialPort;
|
||||||
|
|
||||||
export { port, parser };
|
parser: any;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.path = null;
|
||||||
|
this.port = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
get isOpen() {
|
||||||
|
if (!this.port) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return this.port.isOpen;
|
||||||
|
}
|
||||||
|
|
||||||
|
create(path: string) {
|
||||||
|
this.path = path;
|
||||||
|
this.port = new SerialPort(path, {
|
||||||
|
baudRate: 9600,
|
||||||
|
autoOpen: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
this.parser = this.port.pipe(new parsers.Readline({ delimiter: "\r\n" }));
|
||||||
|
}
|
||||||
|
|
||||||
|
open(callback: (error:Error | null | undefined)=>void) {
|
||||||
|
if (this.isOpen) {
|
||||||
|
throw new Error("Port already open");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.port === null) {
|
||||||
|
throw new Error("Port must be created first");
|
||||||
|
}
|
||||||
|
|
||||||
|
this.port.open((error) => callback(error));
|
||||||
|
}
|
||||||
|
|
||||||
|
close() {
|
||||||
|
if (this.port) {
|
||||||
|
this.port.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default PortController;
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
|
import PortController from "../SerialConnection";
|
||||||
|
|
||||||
export default interface ISerialConnectionState {
|
export default interface ISerialConnectionState {
|
||||||
port: null | string;
|
port: string | null;
|
||||||
|
portController: PortController | null;
|
||||||
status: {
|
status: {
|
||||||
connecting: boolean;
|
connecting: boolean;
|
||||||
connected: boolean;
|
connected: boolean;
|
||||||
|
|
36
Dashboard/src/redux/actions/asyncSerialConnectionActions.ts
Normal file
36
Dashboard/src/redux/actions/asyncSerialConnectionActions.ts
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
import { ThunkResult } from "typesafe-actions";
|
||||||
|
import {
|
||||||
|
connectionStart, connectionSuccess, connectionFailure, setPortController, connectionEnd,
|
||||||
|
} from "./serialConnectionActions";
|
||||||
|
import PortController from "../../SerialConnection";
|
||||||
|
|
||||||
|
const connect = (): ThunkResult<void> => async (dispatch, getState) => {
|
||||||
|
const state = getState();
|
||||||
|
dispatch(connectionStart());
|
||||||
|
|
||||||
|
if (state.serialConnection.port === null) {
|
||||||
|
dispatch(connectionFailure(new Error("No Serial Port set")));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const controller = new PortController();
|
||||||
|
controller.create(state.serialConnection.port);
|
||||||
|
|
||||||
|
dispatch(setPortController(controller));
|
||||||
|
|
||||||
|
controller.open((error) => {
|
||||||
|
if (error === null || error === undefined) {
|
||||||
|
dispatch(connectionSuccess());
|
||||||
|
} else {
|
||||||
|
dispatch(connectionFailure(error));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const disconnect = (): ThunkResult<void> => async (dispatch, getState) => {
|
||||||
|
const state = getState();
|
||||||
|
state.serialConnection.portController?.close();
|
||||||
|
dispatch(connectionEnd());
|
||||||
|
};
|
||||||
|
|
||||||
|
export { connect, disconnect };
|
|
@ -1,11 +1,13 @@
|
||||||
import { action } from "typesafe-actions";
|
import { action } from "typesafe-actions";
|
||||||
|
import PortController from "../../SerialConnection";
|
||||||
|
|
||||||
export enum SerialConnectionActionTypes {
|
export enum SerialConnectionActionTypes {
|
||||||
SET_SERIAL_PORT = "SET_SERIAL_PORT",
|
SET_SERIAL_PORT = "SET_SERIAL_PORT",
|
||||||
CONNECTION_START = "CONNECTION_START",
|
CONNECTION_START = "CONNECTION_START",
|
||||||
CONNECTION_SUCCESS = "CONNECTION_SUCCESS",
|
CONNECTION_SUCCESS = "CONNECTION_SUCCESS",
|
||||||
CONNECTION_FAILURE = "CONNECTION_FAILURE",
|
CONNECTION_FAILURE = "CONNECTION_FAILURE",
|
||||||
DISCONNECT = "DISCONNECT",
|
CONNECTION_END = "CONNECTION_END",
|
||||||
|
SET_PORT_CONTROLLER = "SET_PORT_CONTROLLER"
|
||||||
}
|
}
|
||||||
|
|
||||||
export const setSerialPort = (port: string) => action(SerialConnectionActionTypes.SET_SERIAL_PORT, port);
|
export const setSerialPort = (port: string) => action(SerialConnectionActionTypes.SET_SERIAL_PORT, port);
|
||||||
|
@ -16,4 +18,6 @@ export const connectionSuccess = () => action(SerialConnectionActionTypes.CONNEC
|
||||||
|
|
||||||
export const connectionFailure = (error: Error) => action(SerialConnectionActionTypes.CONNECTION_FAILURE, error);
|
export const connectionFailure = (error: Error) => action(SerialConnectionActionTypes.CONNECTION_FAILURE, error);
|
||||||
|
|
||||||
export const disconnect = () => action(SerialConnectionActionTypes.DISCONNECT);
|
export const connectionEnd = () => action(SerialConnectionActionTypes.CONNECTION_END);
|
||||||
|
|
||||||
|
export const setPortController = (controller: PortController) => action(SerialConnectionActionTypes.SET_PORT_CONTROLLER, controller);
|
||||||
|
|
|
@ -4,6 +4,7 @@ import { SerialConnectionActionTypes } from "../actions/serialConnectionActions"
|
||||||
|
|
||||||
const initialState: ISerialConnectionState = {
|
const initialState: ISerialConnectionState = {
|
||||||
port: null,
|
port: null,
|
||||||
|
portController: null,
|
||||||
status: {
|
status: {
|
||||||
connecting: false,
|
connecting: false,
|
||||||
connected: false,
|
connected: false,
|
||||||
|
@ -40,13 +41,18 @@ const SerialConnectionReducer = createReducer(initialState)
|
||||||
error: null,
|
error: null,
|
||||||
},
|
},
|
||||||
}))
|
}))
|
||||||
.handleType(SerialConnectionActionTypes.DISCONNECT, (state) => ({
|
.handleType(SerialConnectionActionTypes.CONNECTION_END, (state) => ({
|
||||||
...state,
|
...state,
|
||||||
|
portController: null,
|
||||||
status: {
|
status: {
|
||||||
connecting: false,
|
connecting: false,
|
||||||
connected: false,
|
connected: false,
|
||||||
error: null,
|
error: null,
|
||||||
},
|
},
|
||||||
|
}))
|
||||||
|
.handleType(SerialConnectionActionTypes.SET_PORT_CONTROLLER, (state, action) => ({
|
||||||
|
...state,
|
||||||
|
portController: action.payload,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export default SerialConnectionReducer;
|
export default SerialConnectionReducer;
|
||||||
|
|
Reference in a new issue