Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
Tags
- c# datagridview 데이터 넣기
- setInterval 정지
- AntDesign
- pm2 시작
- pm2 상태 확인
- mosquitto.conf
- invalid data
- 1883
- transfer
- allow_anonymouse
- setInterval 중지
- datagridview 직접입력
- 서버동기화
- mosquitto
- 맥 어드레스
- timepicker
- 공인IP
- setInterval clear
- DatePicker
- setInterval 외부 정지
- pm2 확인
- listener 1883
- mySQL_Replication
- Replication
- html #select #option #multiple
- pm2 설치
- 데이터테이블 데이터 넣기
- DataGridView 직접 입력
- map이 undefined가 뜰 때
- pm2
Archives
- Today
- Total
개발 노트
자료구조 변경 비교 본문
기존 : mqtt 수신내역을 배열형태로 일괄적으로 담음
변경 후 : mqtt수신 시 farmCode기준으로 묶어서 내부에 필요한 정보만 저장
기존 호출 컴포넌트
const ResizableComponent: React.FC<ResizableProps> = () => {
const workerRef = useRef<Worker | null>(null);
const { messages, addMessage } = useMqttStore();
useEffect(() => {
const URL = '/mqttWorker.built.js';
if (!workerRef.current) {
const worker = new Worker(URL);
workerRef.current = worker;
workerRef.current.onmessage = function (event) {
// console.log(typeof event.data.message);
if (event.data.message) {
const messageTime = extractTime(event.data.message);
const currentTime = new Date()
.toLocaleString('ko-KR', {
hour12: false,
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
second: '2-digit',
})
.replace(/. \d{4}/, '')
.replace(/(\d{4})\. (\d{2})\. (\d{2})\. (\d{2}):(\d{2}):(\d{2})/, '$1-$2-$3 $4:$5:$6');
const now = new Date();
const sevenDaysAgo = new Date(now.setDate(now.getDate() - 7));
if (new Date(messageTime) >= sevenDaysAgo) {
const splitTopic = event.data.topic.split('/');
const farmCode = splitTopic.length > 2 ? splitTopic[2] : '';
// 메시지 객체 생성
const messageObject = {
topic: event.data.topic,
message: event.data.message,
time: messageTime,
currentTime: currentTime,
};
addMessage(payload);
}
}
};
if (workerRef.current) {
workerRef.current.postMessage({ CMD: 'MQTT_START' });
workerRef.current.postMessage({
CMD: 'MQTT_SUBSCIBE',
DATA: ['dawoon/ALIVE/#', 'dawoon/Robot/#', 'dawoon/RMAN/#', 'dawoon/Feeder/#', 'dawoon/SMARTGATE/#'],
});
}
}
return function cleanup() {
if (workerRef.current) {
workerRef.current.terminate();
workerRef.current = null;
}
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
변경 호출컴포넌트 => 그룹으로 변경
const ResizableComponent: React.FC<ResizableProps> = () => {
const workerRef = useRef<Worker | null>(null);
const {groupedMessages, addGroupedMessage } = useGroupedMqttStore()
useEffect(() => {
const URL = '/mqttWorker.built.js';
if (!workerRef.current) {
const worker = new Worker(URL);
workerRef.current = worker;
workerRef.current.onmessage = function (event) {
// console.log(typeof event.data.message);
if (event.data.message) {
const messageTime = extractTime(event.data.message);
const currentTime = new Date()
.toLocaleString('ko-KR', {
hour12: false,
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
second: '2-digit',
})
.replace(/. \d{4}/, '')
.replace(/(\d{4})\. (\d{2})\. (\d{2})\. (\d{2}):(\d{2}):(\d{2})/, '$1-$2-$3 $4:$5:$6');
const now = new Date();
const sevenDaysAgo = new Date(now.setDate(now.getDate() - 7));
if (new Date(messageTime) >= sevenDaysAgo) {
const splitTopic = event.data.topic.split('/');
const farmCode = splitTopic.length > 2 ? splitTopic[2] : '';
// 메시지 객체 생성
const messageObject = {
topic: event.data.topic,
message: event.data.message,
time: messageTime,
currentTime: currentTime,
};
// addGroupedMessage를 사용하여 메시지 추가
addGroupedMessage(farmCode, messageObject);
}
}
};
if (workerRef.current) {
workerRef.current.postMessage({ CMD: 'MQTT_START' });
workerRef.current.postMessage({
CMD: 'MQTT_SUBSCIBE',
DATA: ['dawoon/ALIVE/#', 'dawoon/Robot/#', 'dawoon/RMAN/#', 'dawoon/Feeder/#', 'dawoon/SMARTGATE/#'],
});
}
}
return function cleanup() {
if (workerRef.current) {
workerRef.current.terminate();
workerRef.current = null;
}
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
변경 전 zustand store코드
- 배열에 담는 구조여서 같은내용을 중복처리 하지 않기 위한 코드 필요
- 배열에 필요한내용을 추가적으로 담는 구조로 배열의 내용자체가 많고 무거워짐
export const useMqttStore = create<Store>((set, get) => ({
messages: [],
addMessage: (payload: Message) => {
const splitTopic = payload.topic.split('/');
const parsedMessage = JSON.parse(payload.message);
const cmd = parsedMessage.CMD;
// 특정 조건에 따라 추가 필드 설정
let additionalFields = {};
//추가 설정 내역 생략
// 이름값 가져오기
if ('FNAME' in parsedMessage || 'FARMNAME' in parsedMessage) {
additionalFields = { ...additionalFields, farmName: parsedMessage.FARMNAME || parsedMessage.FNAME };
}
// 새로운 메시지를 추가하는 함수
set((state) => {
// 이전 메시지 중 중복되지 않은 메시지만을 필터링하여 새 배열을 생성
const noDuplicateArray = state.messages.filter((message) => {
// 메시지의 topic을 '/'를 기준으로 분리
const splitTopic = message.topic.split('/');
// 분리된 topic의 세 번째 항목이 farmCode
const farmCode = splitTopic.length > 2 ? splitTopic[2] : '';
let parsedMessage;
try {
// 메시지의 내용을 JSON 형태로 파싱
parsedMessage = JSON.parse(message.message);
} catch (error) {
// JSON 파싱에 실패한 경우 오류를 출력하고, 해당 메시지는 필터링에서 제외
console.error('Invalid JSON:', message.message);
return true;
}
// 메시지의 CMD를 가져옴
const cmd = parsedMessage.CMD;
if (farmCode === splitTopic[2] && message.topic === payload.topic && cmd === parsedMessage.CMD) {
// CMD가 "MAIN_ERROR" 또는 "ERROR_SMARTGATE"가 아니라면, 중복으로 판단하고 필터링
if (cmd !== "MAIN_ERROR" && cmd !== "ERROR_SMARTGATE") {
// array filter에 의해 noDuplicateArray에 포함하지 않음
return false;
}
}
// 위의 조건들에 해당하지 않는 메시지는 필터링에서 제외하지 않음
// array filter에 의해 noDuplicateArray에 포함함
return true;
});
// 필터링된 메시지 배열에 새 메시지를 추가하여 상태를 업데이트
return {
messages: [...noDuplicateArray, { ...payload, additionalFields }],
};
});
},
변경 후 zustand store 코드
- 그룹화해서 묶어서 객체형태로 저장(farmCode를 key값으로 가짐)
- 기존에 가져온 데이터에서 필요한 내용만 추출하여 저장
- 저장형태를 미리 지정 후(typescript) 그 형태에 맞춰서 지정
import { extractTime } from '@/utils/extractTime';
import { create } from 'zustand';
interface Message {
topic: string;
time: string;
message: any;
currentTime: string;
additionalFields?: {
[key: string]: any;
};
}
interface GroupedMessages {
[farmCode: string]: {
robot: { [key: string]: any };
smartgate: { [key: string]: any };
rman: { [key: string]: any };
web: { [key: string]: any };
feeder: { [key: string]: any };
errorList: Message[];
currentTime: string;
time: string;
};
}
interface State {
groupedMessages: GroupedMessages;
addGroupedMessage: (farmCode: string, messageObject: Message) => void;
}
const useGroupedMqttStore = create<State>((set) => ({
groupedMessages: {},
addGroupedMessage: (farmCode, messageObject) =>
set((state) => {
// cmd 필드가 있을 경우 바로 JSON.parse 적용
if (messageObject.message) {
try {
// message 필드가 JSON 문자열이면 파싱
const message = JSON.parse(messageObject.message);
messageObject.message = message;
} catch (e) {
console.error('message 파싱 오류:', e);
}
}
// 기존 메시지들을 가져옴
const existingGroup = state.groupedMessages[farmCode] || {
robot: {},
smartgate: {},
rman: {},
web: {},
errorList: [],
feeder:{},
currentTime: messageObject.currentTime,
time: messageObject.time,
};
// 새 메시지에 대한 추가 필드 설정 로직
const cmd = messageObject.message.CMD;
const splitTopic = messageObject.topic.split('/');
let additionalFields = {};
//추가 필드 설정 삭제
// 메시지를 관련된 객체에 추가
const messageType = messageObject.topic.split('/')[1].toUpperCase();
switch (messageType) {
case 'ROBOT':
existingGroup.robot = { ...existingGroup.robot, ...messageObject.additionalFields };
if (cmd==='MAIN_ERROR') {
existingGroup.errorList.push(messageObject)
}
break;
case 'SMARTGATE':
existingGroup.smartgate = { ...existingGroup.smartgate, ...messageObject.additionalFields };
if (cmd==='ERROR_SMARTGATE') {
existingGroup.errorList.push(messageObject)
}
break;
case 'RMAN':
existingGroup.rman = { ...existingGroup.rman, ...messageObject.additionalFields };
break;
case 'ALIVE':
if (messageObject.topic.split('/')[1].toUpperCase()==='RMAN'){
existingGroup.rman = { ...existingGroup.rman, ...messageObject.additionalFields };
}
if (messageObject.topic.split('/')[1].toUpperCase()==='WEB'){
existingGroup.web = { ...existingGroup.web, ...messageObject.additionalFields };
}
break;
case 'FEEDER':
existingGroup.feeder = { ...existingGroup.feeder, ...messageObject.additionalFields };
break;
default:
console.error('Unknown message type:', messageType);
}
// 상태를 업데이트
return {
groupedMessages: {
...state.groupedMessages,
[farmCode]: existingGroup,
},
};
}),
}));
export default useGroupedMqttStore;
'React' 카테고리의 다른 글
modal dialog component만들기 (0) | 2024.03.20 |
---|---|
필터기능 구현 (0) | 2024.03.18 |
Next.js에서 mysql2 연결하기 (net error 해결기) (0) | 2024.02.29 |
mqtt연결 시 connected반복 에러 (0) | 2024.02.28 |
정렬기능 보완 (0) | 2024.02.27 |