개발 노트

web-worker로 가져온 MQTT Data를 세부 컴포넌트에 적용시키기 본문

React

web-worker로 가져온 MQTT Data를 세부 컴포넌트에 적용시키기

한츄 2024. 2. 26. 17:58

1. 초기에 필요한 모양으로 받아온 값 처리

import { extractTime } from '@/utils/extractTime';
import { create } from 'zustand';

export type Message = {
  topic: string;
  message: string;
  time: string;
  additionalFields?: {
    [key: string]: any;
  };
};

type Store = {
  messages: Message[];
  addMessage: (payload: Message) => void;
  findMessagesByTopics: (topics: string[]) => Message[];
};

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 (splitTopic[1] === 'Robot') {
      if (cmd === 'ROBOT_STATUS') {
        additionalFields = {
          robotMessage: parsedMessage.WORK === 'MILK' ? '착유 중' : '대기 중',
          robotRunningTime: extractTime(payload.message),
          robotCount: splitTopic[3],
        };
      } else if (cmd === 'MILKEND') {
        additionalFields = {
          robotMessage: '착유 완료',
          robotRunningTime: extractTime(payload.message),
          robotCount: splitTopic[3],
        };
	/* 나머지 코드 생략 */
    }

// 이름값 가져오기
    if ('FNAME' in parsedMessage || 'FARMNAME' in parsedMessage) {
      additionalFields = { ...additionalFields, farmName: parsedMessage.FARMNAME || parsedMessage.FNAME };
    }
    // 추가 필드를 포함한 메시지를 저장
    set((state) => {
      const messagesWithoutDuplicates = state.messages.filter((message) => {
        // 같은 농장 코드이면서, 같은 주제를 가지고 있고, 같은 CMD를 가진 메시지는 제외(중복처리)
        const splitTopic = message.topic.split('/');
        const farmCode = splitTopic.length > 2 ? splitTopic[2] : '';
        const parsedMessage = JSON.parse(message.message);
        const cmd = parsedMessage.CMD;

        return !(farmCode === splitTopic[2] && message.topic === payload.topic && cmd === parsedMessage.CMD);
      });

      return {
        messages: [...messagesWithoutDuplicates, { ...payload, additionalFields }],
      };
    });
  },
  findMessagesByTopics: (topics: string[]) => {
    const store = get();
    return store.messages.filter((message) => topics.includes(message.topic));
  },
}));

받아온 값을 바로 처리하여 배열에 저장하도록 설정합니다.

 

2. 컴포넌트에서 상위컴포넌트로 값을 전달합니다

      {/* 농장 이름 가져오기 */}
      <FarmName farmName={farmName} errorState={errorState} />
      {/* 농장의 cpu/memory/hdd/mysql 정보 */}
      <FarmStateItem className="-mt-1" cpu={cpu} ram={ram} hdd={hdd} sql={sql} />
      {/* robot/gate 데이터 */}
      <ul className="flex flex-col gap-y-1">
        {robotCount && (
          <FarmRobotList
            count={robotCount}
            message={robotMessage}
            errorState={robotErrorState}
            robotRunningTime={robotRunningTime}
          />
        )}
        {gateCount && (
          <FarmGateList
            count={gateCount}
            message={gateMessage}
            errorState={gateErrorState}
            gateRunningTime={gateRunningTime}
          />
        )}
      </ul>
      <FarmRmanWeb
        rmanTime={rmanTime}
        webTime={webTime}
        rmanErrorState={rmanErrorState}
        webErrorState={webErrorState}
      />

 

3. 상위컴포넌트에서 필요한 값을 불러들여 map으로 순환

        {sortedFarmCodes.map((farmCode) => {
          const { additionalFields } = groupedMessages[farmCode];
          return (
            <FarmItem
              key={farmCode}
              cpu={additionalFields.cpu}
              ram={additionalFields.ram}
              hdd={additionalFields.hdd}
              sql={additionalFields.sql}
              farmName={`${additionalFields.farmName} (${farmCode})`}
              errorState={additionalFields.errorState}
              errorList={additionalFields.errorList}
              robotCount={additionalFields.robotCount}
              gateCount={additionalFields.gateCount}
              robotMessage={additionalFields.robotMessage}
              gateMessage={additionalFields.gateMessage}
              robotErrorState={additionalFields.robotErrorState}
              gateErrorState={additionalFields.gateErrorState}
              robotRunningTime={additionalFields.robotRunningTime}
              gateRunningTime={additionalFields.gateRunningTime}
              rmanTime={additionalFields.rmanTime}
              webTime={additionalFields.webTime}
              rmanErrorState={additionalFields.rmanErrorState}
              webErrorState={additionalFields.webErrorState}
            />
          );
        })}