이정민

lib

1 +const mysql = require('mysql');
2 +
3 +const DB_option = require('../keys/db_option');
4 +
5 +module.exports = mysql.createConnection(DB_option);
1 +{
2 + "weather": {
3 + "minutely": [
4 + {
5 + "station": {
6 + "longitude": "127.1164",
7 + "latitude": "37.2772",
8 + "name": "기흥구",
9 + "id": "371",
10 + "type": "KMA"
11 + },
12 + "wind": {
13 + "wdir": "189.50",
14 + "wspd": "2.20"
15 + },
16 + "precipitation": {
17 + "sinceOntime": "0.00",
18 + "type": "0"
19 + },
20 + "sky": {
21 + "code": "SKY_A07",
22 + "name": "흐림"
23 + },
24 + "rain": {
25 + "sinceOntime": "0.00",
26 + "sinceMidnight": "",
27 + "last10min": "0.00",
28 + "last15min": "0.00",
29 + "last30min": "0.00",
30 + "last1hour": "0.00",
31 + "last6hour": "0.50",
32 + "last12hour": "0.50",
33 + "last24hour": "0.50"
34 + },
35 + "temperature": {
36 + "tc": "5.90",
37 + "tmax": "7.00",
38 + "tmin": "-1.00"
39 + },
40 + "humidity": "",
41 + "pressure": {
42 + "surface": "",
43 + "seaLevel": ""
44 + },
45 + "lightning": "0",
46 + "timeObservation": "2018-12-06 14:14:00"
47 + }
48 + ]
49 + },
50 + "common": {
51 + "alertYn": "Y",
52 + "stormYn": "N"
53 + },
54 + "result": {
55 + "code": 9200,
56 + "requestUrl": "/weather/current/minutely?appKey=key&lat=37.239795&lon=127.083240",
57 + "message": "성공"
58 + }
59 +},
60 +{
61 + "weather": {
62 + "wIndex": {
63 + "uvindex": [
64 + {
65 + "grid": {
66 + "city": "경기도",
67 + "county": "수원시",
68 + "village": ""
69 + },
70 + "day00": {
71 + "imageUrl": "http://files.weatherplanet.co.kr/weather/01_FCT/INDEX1/20181209/FCT_IDX_A07_1_2018120906_00D.gif",
72 + "index": "20.00",
73 + "comment": "자외선 걱정 없어요"
74 + },
75 + "day01": {
76 + "imageUrl": "http://files.weatherplanet.co.kr/weather/01_FCT/INDEX1/20181209/FCT_IDX_A07_1_2018120906_01D.gif",
77 + "index": "20.00",
78 + "comment": "자외선 걱정 없어요"
79 + },
80 + "day02": {
81 + "imageUrl": "http://files.weatherplanet.co.kr/weather/01_FCT/INDEX1/20181209/FCT_IDX_A07_1_2018120906_02D.gif",
82 + "index": "10.00",
83 + "comment": "자외선 없는 날입니다"
84 + }
85 + }
86 + ],
87 + "timeRelease": "2018-12-09 06:00:00"
88 + }
89 + },
90 + "common": {
91 + "alertYn": "Y",
92 + "stormYn": "N"
93 + },
94 + "result": {
95 + "code": 9200,
96 + "requestUrl": "/weather/index/uv?appKey=c13b1a68-ef31-4131-a1b7-4069c263f82d&version=1&lat=37.239795&lon=127.083240",
97 + "message": "성공"
98 + }
99 +}{
100 + "weather": {
101 + "wIndex": {
102 + "thIndex": [
103 + {
104 + "grid": {
105 + "city": "경기",
106 + "county": "용인시 기흥구",
107 + "village": "상갈동"
108 + },
109 + "forecast": {
110 + "timeRelease": "2018-12-09 14:00:00",
111 + "index43hour": "37.85",
112 + "index4hour": "38.40",
113 + "index7hour": "34.36",
114 + "index10hour": "31.08",
115 + "index13hour": "31.08",
116 + "index16hour": "27.60",
117 + "index19hour": "35.76",
118 + "index22hour": "44.84",
119 + "index25hour": "47.47",
120 + "index28hour": "42.45",
121 + "index31hour": "39.37",
122 + "index34hour": "37.85",
123 + "index37hour": "36.54",
124 + "index40hour": "35.73",
125 + "index46hour": "42.99",
126 + "index49hour": "39.12",
127 + "index52hour": "37.79",
128 + "index55hour": "37.13",
129 + "index58hour": "36.29",
130 + "index61hour": "",
131 + "index64hour": "",
132 + "index67hour": ""
133 + },
134 + "current": {
135 + "timeRelease": "2018-12-09 14:00:00",
136 + "index": "40.49"
137 + }
138 + }
139 + ]
140 + }
141 + },
142 + "common": {
143 + "alertYn": "Y",
144 + "stormYn": "N"
145 + },
146 + "result": {
147 + "code": 9200,
148 + "requestUrl": "/weather/index/th?appKey=c13b1a68-ef31-4131-a1b7-4069c263f82d&version=1&lat=37.239795&lon=127.083240",
149 + "message": "성공"
150 + }
151 +}
152 +{
153 + "weather": {
154 + "wIndex": {
155 + "heatIndex": [
156 + {
157 + "grid": {
158 + "city": "경기",
159 + "county": "용인시 기흥구",
160 + "village": "상갈동"
161 + },
162 + "forecast": {
163 + "timeRelease": "2018-12-09 14:00:00",
164 + "index4hour": "37.28",
165 + "index7hour": "70.81",
166 + "index10hour": "91.57",
167 + "index13hour": "91.57",
168 + "index16hour": "110.30",
169 + "index19hour": "71.89",
170 + "index22hour": "36.40",
171 + "index25hour": "27.82",
172 + "index28hour": "50.39",
173 + "index31hour": "61.62",
174 + "index34hour": "71.05",
175 + "index37hour": "75.20",
176 + "index40hour": "79.01",
177 + "index43hour": "71.05",
178 + "index46hour": "52.61",
179 + "index49hour": "67.96",
180 + "index52hour": "69.50",
181 + "index55hour": "69.08",
182 + "index58hour": "74.43",
183 + "index61hour": "",
184 + "index64hour": "",
185 + "index67hour": ""
186 + },
187 + "current": {
188 + "timeRelease": "2018-12-09 14:00:00",
189 + "index": "32.79"
190 + }
191 + }
192 + ]
193 + }
194 + },
195 + "common": {
196 + "alertYn": "Y",
197 + "stormYn": "N"
198 + },
199 + "result": {
200 + "code": 9200,
201 + "requestUrl": "/weather/index/heat?appKey=c13b1a68-ef31-4131-a1b7-4069c263f82d&version=1&lat=37.239795&lon=127.083240",
202 + "message": "성공"
203 + }
204 +}
205 +{
206 + "weather": {
207 + "wIndex": {
208 + "wctIndex": [
209 + {
210 + "grid": {
211 + "city": "경기",
212 + "county": "용인시 기흥구",
213 + "village": "상갈동"
214 + },
215 + "forecast": {
216 + "timeRelease": "2018-12-09 14:00:00",
217 + "index43hour": "-2.17",
218 + "index4hour": "-8.15",
219 + "index7hour": "-6.55",
220 + "index10hour": "-7.00",
221 + "index13hour": "-7.63",
222 + "index16hour": "-9.08",
223 + "index19hour": "-4.71",
224 + "index22hour": "1.18",
225 + "index25hour": "1.53",
226 + "index28hour": "-0.47",
227 + "index31hour": "-3.76",
228 + "index34hour": "-2.37",
229 + "index37hour": "-4.67",
230 + "index40hour": "-4.38",
231 + "index46hour": "-0.67",
232 + "index49hour": "-1.18",
233 + "index52hour": "-2.14",
234 + "index55hour": "-1.65",
235 + "index58hour": "-4.23",
236 + "index61hour": "",
237 + "index64hour": "",
238 + "index67hour": ""
239 + },
240 + "current": {
241 + "timeRelease": "2018-12-09 14:00:00",
242 + "index": "-6.22"
243 + }
244 + }
245 + ]
246 + }
247 + },
248 + "common": {
249 + "alertYn": "Y",
250 + "stormYn": "N"
251 + },
252 + "result": {
253 + "code": 9200,
254 + "requestUrl": "/weather/index/wct?appKey=c13b1a68-ef31-4131-a1b7-4069c263f82d&version=1&lat=37.239795&lon=127.083240",
255 + "message": "성공"
256 + }
257 +}
...\ No newline at end of file ...\ No newline at end of file
1 +const db = require('./db.js');
2 +const secret_key = require('../keys/api_option').key;
3 +const requesting = require('request');
4 +const lat = "37.239795";
5 +const lon = "127.083240";
6 +module.exports = (server, app) => {
7 +
8 + const io = require('socket.io')(server, {
9 + transports: ['websocket'] // websocket 사용시 polling 사용을 배제하고 안정적인 websocket만 사용함
10 + });
11 + //명시적 형 선언
12 + let Current_Weather = {};
13 + let Sensible_T = {};
14 + let Heat_index = {};
15 + let Discomport_index = {};
16 + let Ultra_Violet_index = {};
17 + let sending_to_client_info = {};
18 + let client_send = {};
19 + let client_name = "";
20 + let client_birth ;
21 + let Destiny;
22 + let sql;
23 +
24 + let info = {}
25 +
26 + const req_API = (when, what) => {
27 + //async await 사용하기 위하여 promise 사용
28 + return new Promise((resolve, reject) => {
29 + requesting.get({
30 + // api를 요청할 주소 -- 시크릿키,위도,경도 입력
31 + url: `https://api2.sktelecom.com/weather/${when}/${what}?appKey=${secret_key}&lat=${lat}&lon=${lon}`,
32 + json: true
33 + },
34 + //api에게 응답 받았을때 실행되는 callback function
35 + function (err, api_res, api_body) {
36 + //err 존재시 promise reject 호출
37 + if (err) reject(err);
38 +
39 + // api의 response이 있을경우 promise resolve 호출
40 + if (api_res) {
41 + console.log("calling api");
42 + resolve(api_body);
43 + }
44 + });
45 + })
46 +
47 + }
48 + const API_bundle = async () => {
49 +
50 + try {
51 + Current_Weather = await req_API("current", "minutely"); //현재날씨 (분별)
52 + Sensible_T = await req_API("index", "wct"); //체감온도
53 + Heat_index = await req_API("index", "heat"); //열지수
54 + Discomport_index = await req_API("index", "th"); //불쾌지수
55 + Ultra_Violet_index = await req_API("index", "uv"); //자외선지수
56 +
57 + info = {
58 + heat: Heat_index.weather.wIndex.heatIndex[0].current.index, //열지수
59 + sensible_temperature: Sensible_T.weather.wIndex.wctIndex[0].current.index, //체감온도
60 + discomport: Discomport_index.weather.wIndex.thIndex[0].current.index, //불쾌지수
61 + UV: Ultra_Violet_index.weather.wIndex.uvindex[0].day01.index, //자외선지수
62 + windspd: Current_Weather.weather.minutely[0].wind.wspd, //바람 속도
63 + sky: Current_Weather.weather.minutely[0].sky.code, //하늘 상태
64 + rain: Current_Weather.weather.minutely[0].rain.last24hour, //강수량
65 + current_temperature: Current_Weather.weather.minutely[0].temperature.tc, //현재 온도
66 + lightning: Current_Weather.weather.minutely[0].lightning, //현재 낙뢰
67 + warning: Current_Weather.common.alertYn, //현재 특보 유무
68 + typhoon: Current_Weather.common.stormYn, //현재 태풍
69 + time: Current_Weather.weather.minutely[0].timeObservation, // 불러온 시각
70 + death_prob: 0 //확률
71 + }
72 + console.log("API INFO \n", info);
73 +
74 + // ------------------------------ death_prob 정의 ------------------------------
75 +
76 + info.death_prob += info.sky.substr(5) * 1 //하늘 상태에 따라 확률 증가
77 +
78 + if (info.lightning === 1) //낙뢰시에 확률 증가
79 + info.death_prob += 1.5;
80 + if (info.typhoon === "Y") //태풍시에 확률 증가
81 + info.death_prob += 1.5;
82 + if (info.warning === "Y") // 특보 발령시 확률 증가
83 + info.death_prob += 1
84 +
85 + //죽을 확률 계산(내맘대로 커스텀)
86 + info.death_prob = (
87 + (info.heat / 50) + (Math.abs(info.sensible_temperature - 15) / 10) + (info.discomport / 10) + (info.UV / 10)
88 + + info.windspd*1 + (info.rain / 10) + (Math.abs(info.current_temperature - 15) / 10)
89 + );
90 +
91 + //이벤트 기반으로 일정 시간 간격으로 클라이언트에게 보낼 정보
92 + client_send = {
93 + time: info.time,
94 + wind: info.windspd,
95 + temperature: info.current_temperature,
96 + rain: info.rain,
97 + death: info.death_prob
98 + };
99 + function getRandom_add_prob(min, max) {
100 + return Math.random() * (max - min) + min;
101 + }
102 +
103 +
104 + // 심장이 크게 뛰며 확률이 증가하거나 감소 할 수 있음
105 + Math.random() * 2 >= 1 ? client_send.death += getRandom_add_prob(0,5) : client_send.death -= getRandom_add_prob(0,5) ;
106 +
107 +
108 + //운명의 장난으로 죽을 확률이 증가하거나 감소함
109 + const rand = Math.floor(Math.random() * 6) //생년월일 중 한자리 뽑음
110 +
111 + Destiny=client_birth.charAt(rand)/3; //명시적 형 변환
112 + if(Destiny==0)Destiny=1; //사용자 잘못 입력했을때 예외처리
113 + Math.random() * 2 >= 1 ? client_send.death += Destiny : client_send.death -= Destiny ;
114 +
115 +
116 + //만약 날이 너무 안좋아서 확률이 100을 넘긴다면 100으로 예외처리
117 + if (client_send.death >= 100) {
118 + client_send.death = 100;
119 + }
120 +
121 + console.log("client send data \n",client_send)
122 +
123 + app.get("socket").emit("weatherInfo_minutely_send_to_client", client_send); // 클라이언트에게 정보 담아서 이벤트 발산
124 + console.log("emit");
125 +
126 + //db에 저장
127 + sql = "INSERT INTO weatherInfo (time,wind,temperature,rain,prob) VALUES (?,?,?,?,?)";
128 + db.query(sql, [client_send.time, client_send.wind, client_send.temperature, client_send.rain, client_send.death], (err, result) => {
129 + if (err) console.log(err);
130 + })
131 + } catch (err) { //promise err or try err catch
132 + console.log("================Error Occured !!================\n", err);
133 + }
134 + }
135 +
136 + let call_interval;
137 +
138 + const Start_Interval = (second, CALL) => {
139 + CALL(); //처음 불러올때 한번 호출하고
140 + call_interval = setInterval(CALL, second * 1000); //그 후에 1분마다 호출
141 + }
142 +
143 + io.on('connection', (socket) => { //프론트와 소켓 연결시 이벤트 루프 동작
144 +
145 + app.set("socket", socket);
146 + socket.on("connection", (client_data) => {
147 + console.log("SOCKET CONNECTED");
148 + client_name = client_data.name;
149 + client_birth = client_data.birth;
150 + Start_Interval(60, API_bundle); //소켓 연결후 interval 활성화하여 1분마다 API 호출
151 +
152 + });
153 +
154 + socket.on('disconnect', (reason) => {
155 + console.log("disconnected");
156 + clearInterval(call_interval); //연결 종료시 interval 해제
157 + })
158 + })
159 +
160 +}