dataController.js 6.55 KB
Newer Older
1
import fs from "fs";
2
import fetch from "node-fetch";
3
4
import { serverMSG, statusCode } from "../serverinfo";
import { pool as db, dbMSG, pool } from "../db";
5
6
7
import dotenv from "dotenv";

dotenv.config();
8

9
10
11
const OUT = "Out";
const IN = "In";

12
13
14
const OUTSIDE = "Outside";
const USERS = "Users";

15
16
17
const OUT_DATA_HEADER = "date,temp,humi,press,wind_speed\n";
const IN_DATA_HEADER = "date,temp,humi,lights\n";

18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
// 데이터 수집 기로 부터 받아온 지역 코드 세분화
const locCodeSep = (code = "") => {
  const DO = code.slice(0, 2);
  const SGG = code.slice(0, 5);
  const EMD = code;

  const loc = {
    DO: DO,
    SGG: SGG,
    EMD: EMD,
  };

  return loc;
};

// 데이터가 들어온 시간 데이터 생성
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
const getTimeInfo = (date = null) => {
  let time;
  if (date == null) {
    const now = new Date();

    const year = now.getFullYear();
    const month = now.getMonth() + 1;
    const date = now.getDate();
    const hour = now.getHours();
    const minute = now.getMinutes();

    time = {
      year: year,
      month: month < 10 ? `0${month}` : month,
      date: date < 10 ? `0${date}` : date,
      hour: hour < 10 ? `0${hour}` : hour,
      minute: minute < 10 ? `0${minute}` : hour,
    };
  } else {
    time = {
      year: date.substring(0, 4),
      month: date.substring(4, 6),
      date: date.substring(6, 8),
      hour: date.substring(8, 10),
      minute: date.substring(10),
    };
  }
61
62
63
64

  return time;
};

65
66
// Data 접근 경로 반환, DB에 존재 하지 않을 시 Update 동작
const getDataDIR = async (loc, time, type, id) => {
67
  const year = time.year;
68
69
  const month = time.month;
  const date = time.date;
70

71
72
73
74
75
76
  const select_query =
    "SELECT DATALINK" +
    " " +
    `FROM ${type === OUT ? "LOCINFO" : "USER"}` +
    " " +
    `WHERE ${type === OUT ? `CODE=${loc.EMD}` : `ID='${id}'`}`;
77

78
79
  const [row, fields] = await db.execute(select_query);

80
81
82
  let baseDIR;
  if (row.length != 0) baseDIR = row[0]["DATALINK"];
  else baseDIR = null;
83
84
85
86

  // DB에 Data 저장 경로가 존재하지 않을 시 UPDATE
  if (baseDIR === null) {
    baseDIR =
87
      "/data" +
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
      `/${loc.DO}` +
      `/${loc.SGG}` +
      `/${loc.EMD}` +
      `/${type === OUT ? OUTSIDE : USERS + "/" + id}`;

    const update_query =
      `UPDATE ${type === OUT ? "LOCINFO" : "USER"}` +
      " " +
      `SET DATALINK='${baseDIR}'` +
      " " +
      `WHERE ${type === OUT ? `CODE=${loc.EMD}` : `ID='${id}'`}`;

    db.execute(update_query);
  }

  const timeDIR = `/${year}` + `/${year}${month}` + `/${year}${month}${date}`;

105
106
107
108
109
  // 지역별 통합 데이터와 지역+날짜별 Data 저장소 경로
  const dirs = {
    base: process.env.LOCAL_SERVER_DIR + baseDIR,
    time: timeDIR,
  };
110

111
  return dirs;
112
113
};

114
// 데이터를 파일 형식으로 저장
115
const storeData = (type, time, loc, dir, data) => {
116
  const fileName = "weather.csv";
117

118
  fs.open(dir + `/${fileName}`, "a", (err, fd) => {
119
120
121
122
123
    if (err) {
      // Directory가 존재하지 않는 경우, 생성
      if (err.code === "ENOENT") {
        console.log("There is no directory.");

124
125
126
127
        fs.mkdirSync(dir, { recursive: true }, (err) => {
          if (err) console.log(err);
        });

128
        // 디렉토리를 새로 생성하는 경우 header 추가 및 데이터 추가.
129
        const header = type == OUT ? OUT_DATA_HEADER : IN_DATA_HEADER;
130
        fs.appendFile(dir + `/${fileName}`, header + data, (err) => {
131
          if (err) console.log(err);
132
133
          else {
            console.log("Create directory and record header.");
134
135
136
137
138
            console.log(
              `${time.year}/${time.month}/${time.date} ${time.hour}:${
                time.minute
              } - ${loc.EMD} ${type === OUT ? OUTSIDE : USERS} data append.`
            );
139
          }
140
        });
141
142
143
      }
      // 그 외의 에러는 출력
      else console.log(err);
144
    }
145
146
147
148
149
150
151
152
153
154
155
156
    // 디렉토리가 존재하는 경우 실행
    else {
      fs.appendFile(dir + `/${fileName}`, data, (err) => {
        if (err) console.log(err);
        else
          console.log(
            `${time.year}/${time.month}/${time.date} ${time.hour}:${
              time.minute
            } - ${loc.EMD} ${type === OUT ? OUTSIDE : USERS} data append.`
          );
      });
    }
157
158
159
160
  });
};

// 외부 수집기로 부터 들어온 정보 처리
161
const handleOutData = async (locCode, date, lat, lng) => {
162
  // OpenWeatherAPI로 부터 지역의 날씨 정보획득을 위해 지역의 경도와 위도, API Key, 단위 기준 metric 전달
163
  const response = await fetch(
164
    `https://api.openweathermap.org/data/2.5/weather?lat=${lat}&lon=${lng}&appid=${process.env.OPENWEATHERMAP_API_KEY}&units=metric`
165
166
167
168
169
170
171
172
173
  );
  const json = await response.json();

  const temp = json["main"]["temp"];
  const humi = json["main"]["humidity"];
  const press = json["main"]["pressure"];
  const wind_speed = json["wind"]["speed"];

  const loc = locCodeSep(locCode);
174
  const time = getTimeInfo(date);
175

176
  const dirs = await getDataDIR(loc, time, OUT, OUTSIDE);
177

178
  // 데이터 형식 - [ 연 월 일 시 분 | 온도 | 습도 | 기압 | 풍속 ]
179
  const data = `${date},${temp},${humi},${press},${wind_speed}\n`;
180

181
182
  storeData(OUT, time, loc, dirs.base, data);
  storeData(OUT, time, loc, dirs.base + dirs.time, data);
183
184
185
};

// 내부 수집기로 부터 들어온 정보 처리
186
const handleInData = async (id, locCode, date, temp, humi, lights) => {
187
  const loc = locCodeSep(locCode);
188
  const time = getTimeInfo(date);
189

190
191
192
  const dirs = await getDataDIR(loc, time, IN, id);

  // 데이터 형식 - [ 연 월 일 시 분 | 온도 | 습도 | 광도 ]
193
  const data = `${date},${temp},${humi},${lights}\n`;
194

195
196
  storeData(IN, time, loc, dirs.base, data);
  storeData(IN, time, loc, dirs.base + dirs.time, data);
197
198
199
};

// 데이터 수신 처리
200
export const getDataInput = (req, res) => {
201
202
203
204
  try {
    if (req.query.type === OUT) {
      // 외부 데이터 수집기
      const {
205
        query: { locCode, date, lat, lng },
206
      } = req;
207

208
209
      console.log(locCode, date, lat, lng);
      // handleOutData(locCode, date, lat, lng);
210
211
212
    } else {
      // 내부 데이터 수집기 동작
      const {
213
        query: { id, locCode, date, temp, humi, lights },
214
215
      } = req;

216
217
      console.log(id, locCode, date, temp, humi, lights);
      // handleInData(id, locCode, date, temp, humi, lights);
218
219
    }

220
    res.status(statusCode.ok).send(serverMSG.server_ok);
221
222
  } catch (error) {
    console.log(error);
223
    res.status(statusCode.err).send(serverMSG.server_err);
224
  }
KangMin An's avatar
KangMin An committed
225
};
226
227
228
229
230
231
232
233
234

// 사용자의 데이터 가져오기 및 예측 값 전송
export const getUserData = (req, res) => {
  const {
    params: { id },
  } = req;

  res.status(statusCode.ok).send(serverMSG.server_ok);
};