Showing
8 changed files
with
157 additions
and
86 deletions
... | @@ -8,6 +8,7 @@ const Mongoose = require('mongoose'); | ... | @@ -8,6 +8,7 @@ const Mongoose = require('mongoose'); |
8 | const api = require('./src/api'); | 8 | const api = require('./src/api'); |
9 | const MqttServer = require('./src/util/MqttServer'); | 9 | const MqttServer = require('./src/util/MqttServer'); |
10 | const BatchSystem = require('./src/util/Batch'); | 10 | const BatchSystem = require('./src/util/Batch'); |
11 | +const FCM = require('./src/util/FCM'); | ||
11 | 12 | ||
12 | require('dotenv').config(); | 13 | require('dotenv').config(); |
13 | // eslint-disable-next-line no-undef | 14 | // eslint-disable-next-line no-undef |
... | @@ -37,5 +38,7 @@ app.use(router.routes()).use(router.allowedMethods()); | ... | @@ -37,5 +38,7 @@ app.use(router.routes()).use(router.allowedMethods()); |
37 | app.listen(SERVER_PORT, () => { | 38 | app.listen(SERVER_PORT, () => { |
38 | console.log('\x1b[1;36mPORT : ', SERVER_PORT, 'is connected\x1b[0m'); | 39 | console.log('\x1b[1;36mPORT : ', SERVER_PORT, 'is connected\x1b[0m'); |
39 | MqttServer.on(); | 40 | MqttServer.on(); |
40 | - BatchSystem.PushNotifyByDosage(); | 41 | + FCM.initializeFCM(); |
42 | + BatchSystem.removeQrCode(); | ||
43 | + BatchSystem.pushNotifyByDosage(); | ||
41 | }); | 44 | }); |
... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
This diff could not be displayed because it is too large.
... | @@ -19,6 +19,7 @@ | ... | @@ -19,6 +19,7 @@ |
19 | "dependencies": { | 19 | "dependencies": { |
20 | "@google-cloud/storage": "^5.14.2", | 20 | "@google-cloud/storage": "^5.14.2", |
21 | "@koa/cors": "^3.1.0", | 21 | "@koa/cors": "^3.1.0", |
22 | + "firebase-admin": "^9.11.1", | ||
22 | "koa-body": "^4.2.0", | 23 | "koa-body": "^4.2.0", |
23 | "moment": "^2.29.1", | 24 | "moment": "^2.29.1", |
24 | "moment-timezone": "^0.5.33", | 25 | "moment-timezone": "^0.5.33", | ... | ... |
... | @@ -17,6 +17,7 @@ exports.register = async(ctx) => { | ... | @@ -17,6 +17,7 @@ exports.register = async(ctx) => { |
17 | userNm, | 17 | userNm, |
18 | birth, | 18 | birth, |
19 | contact, | 19 | contact, |
20 | + deviceToken, | ||
20 | } = ctx.request.body; | 21 | } = ctx.request.body; |
21 | 22 | ||
22 | const schema = Joi.object().keys({ | 23 | const schema = Joi.object().keys({ |
... | @@ -58,7 +59,8 @@ exports.register = async(ctx) => { | ... | @@ -58,7 +59,8 @@ exports.register = async(ctx) => { |
58 | userId, | 59 | userId, |
59 | userNm, | 60 | userNm, |
60 | birth, | 61 | birth, |
61 | - contact, | 62 | + contact, |
63 | + deviceToken, | ||
62 | }); | 64 | }); |
63 | 65 | ||
64 | await user.save(); | 66 | await user.save(); |
... | @@ -192,7 +194,7 @@ exports.doctorRegister = async ctx => { | ... | @@ -192,7 +194,7 @@ exports.doctorRegister = async ctx => { |
192 | } | 194 | } |
193 | 195 | ||
194 | exports.login = async(ctx) => { | 196 | exports.login = async(ctx) => { |
195 | - const { userId, password } = ctx.request.body; | 197 | + const { userId, password, deviceToken } = ctx.request.body; |
196 | 198 | ||
197 | const schema = Joi.object().keys({ | 199 | const schema = Joi.object().keys({ |
198 | userId : Joi.string().email().max(50).required(), | 200 | userId : Joi.string().email().max(50).required(), |
... | @@ -225,7 +227,6 @@ exports.login = async(ctx) => { | ... | @@ -225,7 +227,6 @@ exports.login = async(ctx) => { |
225 | }; | 227 | }; |
226 | return; | 228 | return; |
227 | } | 229 | } |
228 | - | ||
229 | if(user.useYn !== 'Y') { | 230 | if(user.useYn !== 'Y') { |
230 | ctx.status = 403; | 231 | ctx.status = 403; |
231 | ctx.body = { | 232 | ctx.body = { |
... | @@ -234,6 +235,16 @@ exports.login = async(ctx) => { | ... | @@ -234,6 +235,16 @@ exports.login = async(ctx) => { |
234 | return; | 235 | return; |
235 | } | 236 | } |
236 | 237 | ||
238 | + //일반 유저의 deviceToken값이 바뀌면 업데이트한다 = 기기가 바뀌면 | ||
239 | + if(user.userTypeCd === 'NORMAL') { | ||
240 | + const profile = await Profile.findByUserId(user.userId); | ||
241 | + if(deviceToken && profile.deviceToken !== deviceToken) { | ||
242 | + profile.updateDeviceToken(deviceToken); | ||
243 | + await profile.save(); | ||
244 | + } | ||
245 | + } | ||
246 | + | ||
247 | + | ||
237 | const token = await user.generateToken(); | 248 | const token = await user.generateToken(); |
238 | ctx.cookies.set('access_token', token, { | 249 | ctx.cookies.set('access_token', token, { |
239 | httpOnly : true, | 250 | httpOnly : true, |
... | @@ -243,7 +254,7 @@ exports.login = async(ctx) => { | ... | @@ -243,7 +254,7 @@ exports.login = async(ctx) => { |
243 | ctx.status = 200; | 254 | ctx.status = 200; |
244 | ctx.body = { | 255 | ctx.body = { |
245 | userTypeCd : user.userTypeCd, | 256 | userTypeCd : user.userTypeCd, |
246 | - token | 257 | + token, |
247 | }; | 258 | }; |
248 | 259 | ||
249 | }; | 260 | }; | ... | ... |
... | @@ -6,17 +6,20 @@ | ... | @@ -6,17 +6,20 @@ |
6 | * 1) Dosage에 따라, Push Notification 발송 | 6 | * 1) Dosage에 따라, Push Notification 발송 |
7 | */ | 7 | */ |
8 | 8 | ||
9 | - const cron = require('node-cron'); | 9 | +const cron = require('node-cron'); |
10 | +const fs = require('fs'); | ||
10 | 11 | ||
11 | - const Profile = require('../models/profile'); | 12 | +const Profile = require('../models/profile'); |
12 | - const User = require('../models/user'); | 13 | +const User = require('../models/user'); |
13 | - const Hub = require('../models/hub'); | 14 | +const Hub = require('../models/hub'); |
14 | - const Bottle = require('../models/bottle'); | 15 | +const Bottle = require('../models/bottle'); |
15 | - const BottleMedicine = require('../models/bottleMedicine'); | 16 | +const BottleMedicine = require('../models/bottleMedicine'); |
17 | +const Medicine = require('../models/medicine'); | ||
16 | 18 | ||
17 | const updateMedicineInfo = require('../lib/UpdatingMedicineInfo'); | 19 | const updateMedicineInfo = require('../lib/UpdatingMedicineInfo'); |
18 | - | 20 | +const { sendPushMessage } = require('./FCM'); |
19 | - | 21 | + |
22 | + | ||
20 | // //매년 1월 1일 00시 00분에 1살씩 추가 | 23 | // //매년 1월 1일 00시 00분에 1살씩 추가 |
21 | // exports.CheckNewYear = () => { | 24 | // exports.CheckNewYear = () => { |
22 | // cron.schedule('0 0 0 1 1 *', async () => { | 25 | // cron.schedule('0 0 0 1 1 *', async () => { |
... | @@ -25,7 +28,7 @@ const updateMedicineInfo = require('../lib/UpdatingMedicineInfo'); | ... | @@ -25,7 +28,7 @@ const updateMedicineInfo = require('../lib/UpdatingMedicineInfo'); |
25 | // await profile.updateUserAge(); | 28 | // await profile.updateUserAge(); |
26 | // profile.save(); | 29 | // profile.save(); |
27 | // }); | 30 | // }); |
28 | - | 31 | + |
29 | // }, { | 32 | // }, { |
30 | // timezone : 'Asia/Tokyo', | 33 | // timezone : 'Asia/Tokyo', |
31 | // }); | 34 | // }); |
... | @@ -35,78 +38,111 @@ const updateMedicineInfo = require('../lib/UpdatingMedicineInfo'); | ... | @@ -35,78 +38,111 @@ const updateMedicineInfo = require('../lib/UpdatingMedicineInfo'); |
35 | exports.updateMedicineData = async () => { | 38 | exports.updateMedicineData = async () => { |
36 | cron.schedule('0 0 0 1 * *', () => { | 39 | cron.schedule('0 0 0 1 * *', () => { |
37 | updateMedicineInfo.updateMedicineInfo(); | 40 | updateMedicineInfo.updateMedicineInfo(); |
41 | + }, { | ||
42 | + timezone : 'Asia/Tokyo', | ||
38 | }); | 43 | }); |
39 | }; | 44 | }; |
40 | - | 45 | + |
46 | +//매주 일요일마다 불필요한 qrcode 제거 | ||
47 | +exports.removeQrCode = () => { | ||
48 | + cron.schedule('0 0 0 * * 0', () => { | ||
49 | + // eslint-disable-next-line no-undef | ||
50 | + const qrDir = process.env.QR_DIR; | ||
51 | + fs.rm(qrDir, { recursive : true, force : true, }, () => { | ||
52 | + fs.mkdir(qrDir, (err) => { if(err) console.log(err) }); | ||
53 | + }); | ||
54 | + }, { | ||
55 | + timezone : 'Asia/Tokyo', | ||
56 | + }); | ||
57 | +}; | ||
58 | + | ||
41 | //dosage에 따라, Push Notification을 발송한다. | 59 | //dosage에 따라, Push Notification을 발송한다. |
42 | //아침 8시, 점심 12시, 저녁 6시에 한번씩 발송 | 60 | //아침 8시, 점심 12시, 저녁 6시에 한번씩 발송 |
43 | - exports.PushNotifyByDosage = async() => { | 61 | +exports.pushNotifyByDosage = async() => { |
44 | - | 62 | + |
45 | - //매일 아침 8시 : 복용량 상관 없이 보냄 | 63 | + //매일 아침 8시 : 복용량 상관 없이 보냄 |
46 | - cron.schedule('0 0 8 * * *', async () => { | 64 | + cron.schedule('0 0 8 * * *', async () => { |
47 | - const bottleMedicineList = await BottleMedicine.find({ useYn : 'Y', dosage : { $gte : 1 } }); | 65 | + const bottleMedicineList = await BottleMedicine.find({ useYn : 'Y', dosage : { $gte : 1 } }); |
48 | - bottleMedicineList.forEach(async bottleMedicine => { | 66 | + bottleMedicineList.forEach(async bottleMedicine => { |
49 | - const bottle = await Bottle.findOne({ bottleId : bottleMedicine.bottleId }); | 67 | + const bottle = await Bottle.findOne({ bottleId : bottleMedicine.bottleId }); |
50 | - const hub = await Hub.findOne({ hubId : bottle.hubId }); | 68 | + const hub = await Hub.findOne({ hubId : bottle.hubId }); |
51 | - const user = await User.findOne({ userId : hub.userId, useYn : 'Y' }); | 69 | + const user = await User.findOne({ userId : hub.userId, useYn : 'Y' }); |
52 | - | 70 | + |
53 | - if(user) { | 71 | + if(user) { |
54 | - const profile = await Profile.findOne({ userId : user.userId }); | 72 | + const profile = await Profile.findOne({ userId : user.userId }); |
55 | - | 73 | + const { deviceToken } = profile; |
56 | - const { deviceToken } = profile; | 74 | + |
57 | - PushNotify(deviceToken); | 75 | + if(deviceToken) { |
58 | - } | 76 | + const medicine = await Medicine.findOne({ medicineId : bottleMedicine.medicineId }); |
59 | - }); | 77 | + pushNotify({ |
60 | - }, { | 78 | + deviceToken, |
61 | - timezone : 'Asia/Tokyo', | 79 | + message : medicine.name + '을 복용하셔야 합니다.', |
62 | - }); | 80 | + }); |
63 | - | 81 | + } |
64 | - | 82 | + } |
65 | - //매일 점심 12시 : 복용량이 3인 환자들만 | 83 | + }); |
66 | - cron.schedule('0 0 12 * * *', async () => { | 84 | + }, { |
67 | - const bottleMedicineList = await BottleMedicine.find({ useYn : 'Y', dosage : { $gte : 3 } }); | 85 | + timezone : 'Asia/Tokyo', |
68 | - bottleMedicineList.forEach(async bottleMedicine => { | 86 | + }); |
69 | - const bottle = await Bottle.findOne({ bottleId : bottleMedicine.bottleId }); | 87 | + |
70 | - const hub = await Hub.findOne({ hubId : bottle.hubId }); | 88 | + |
71 | - const user = await User.findOne({ userId : hub.userId, useYn : 'Y' }); | 89 | + //매일 점심 12시 : 복용량이 3인 환자들만 |
72 | - | 90 | + cron.schedule('0 0 12 * * *', async () => { |
73 | - if(user) { | 91 | + const bottleMedicineList = await BottleMedicine.find({ useYn : 'Y', dosage : { $gte : 3 } }); |
74 | - const profile = await Profile.findOne({ userId : user.userId }); | 92 | + bottleMedicineList.forEach(async bottleMedicine => { |
75 | - | 93 | + const bottle = await Bottle.findOne({ bottleId : bottleMedicine.bottleId }); |
76 | - const { deviceToken } = profile; | 94 | + const hub = await Hub.findOne({ hubId : bottle.hubId }); |
77 | - PushNotify(deviceToken); | 95 | + const user = await User.findOne({ userId : hub.userId, useYn : 'Y' }); |
78 | - } | 96 | + |
79 | - }); | 97 | + if(user) { |
80 | - }, { | 98 | + const profile = await Profile.findOne({ userId : user.userId }); |
81 | - timezone : 'Asia/Tokyo', | 99 | + const { deviceToken } = profile; |
82 | - }); | 100 | + |
83 | - | 101 | + if(deviceToken) { |
84 | - | 102 | + const medicine = await Medicine.findOne({ medicineId : bottleMedicine.medicineId }); |
85 | - //매일 저녁 6시 | 103 | + pushNotify({ |
86 | - cron.schedule('0 0 18 * * *', async () => { | 104 | + deviceToken, |
87 | - const bottleMedicineList = await BottleMedicine.find({ useYn : 'Y', dosage : { $gte : 2 } }); | 105 | + message : medicine.name + '을 복용하셔야 합니다.', |
88 | - bottleMedicineList.forEach(async bottleMedicine => { | 106 | + }); |
89 | - const bottle = await Bottle.findOne({ bottleId : bottleMedicine.bottleId }); | 107 | + } |
90 | - const hub = await Hub.findOne({ hubId : bottle.hubId }); | 108 | + } |
91 | - const user = await User.findOne({ userId : hub.userId, useYn : 'Y' }); | 109 | + }); |
92 | - | 110 | + }, { |
93 | - if(user) { | 111 | + timezone : 'Asia/Tokyo', |
94 | - const profile = await Profile.findOne({ userId : user.userId }); | 112 | + }); |
95 | - | 113 | + |
96 | - const { deviceToken } = profile; | 114 | + |
97 | - PushNotify(deviceToken); | 115 | + //매일 저녁 6시 |
98 | - } | 116 | + cron.schedule('0 0 18 * * *', async () => { |
99 | - }); | 117 | + const bottleMedicineList = await BottleMedicine.find({ useYn : 'Y', dosage : { $gte : 2 } }); |
100 | - }, { | 118 | + bottleMedicineList.forEach(async bottleMedicine => { |
101 | - timezone : 'Asia/Tokyo', | 119 | + const bottle = await Bottle.findOne({ bottleId : bottleMedicine.bottleId }); |
102 | - }); | 120 | + const hub = await Hub.findOne({ hubId : bottle.hubId }); |
103 | - | 121 | + const user = await User.findOne({ userId : hub.userId, useYn : 'Y' }); |
104 | - }; | 122 | + |
105 | - | 123 | + if(user) { |
106 | - const PushNotify = async(deviceToken) => { | 124 | + const profile = await Profile.findOne({ userId : user.userId }); |
125 | + const { deviceToken } = profile; | ||
126 | + | ||
127 | + if(deviceToken) { | ||
128 | + const medicine = await Medicine.findOne({ medicineId : bottleMedicine.medicineId }); | ||
129 | + pushNotify({ | ||
130 | + deviceToken, | ||
131 | + message : medicine.name + '을 복용하셔야 합니다.', | ||
132 | + }); | ||
133 | + } | ||
134 | + } | ||
135 | + }); | ||
136 | + }, { | ||
137 | + timezone : 'Asia/Tokyo', | ||
138 | + }); | ||
139 | + | ||
140 | +}; | ||
141 | + | ||
142 | +const pushNotify = ({ deviceToken, message }) => { | ||
107 | //toDo : deviceToken을 받아서 push notification을 발송하는 함수 | 143 | //toDo : deviceToken을 받아서 push notification을 발송하는 함수 |
108 | - if(deviceToken) { | ||
109 | - console.log(deviceToken); | ||
110 | - } | ||
111 | - }; | ||
112 | - | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
144 | + sendPushMessage({ | ||
145 | + deviceToken, | ||
146 | + message, | ||
147 | + }); | ||
148 | +}; | ... | ... |
server/src/util/FCM.js
0 → 100644
1 | +const fcm = require('firebase-admin'); | ||
2 | + | ||
3 | + | ||
4 | +exports.initializeFCM = () => { | ||
5 | + fcm.initializeApp({ | ||
6 | + credential : fcm.credential.applicationDefault(), | ||
7 | + }); | ||
8 | +}; | ||
9 | + | ||
10 | +exports.sendPushMessage = async ({ deviceToken, message }) => { | ||
11 | + const notifyMessage = { | ||
12 | + notification : { | ||
13 | + title : '약 먹을 시간입니다', | ||
14 | + body : message, | ||
15 | + }, | ||
16 | + token : deviceToken, | ||
17 | + }; | ||
18 | + fcm.messaging().send(notifyMessage); | ||
19 | +}; | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
... | @@ -3,14 +3,15 @@ const moment = require('moment'); | ... | @@ -3,14 +3,15 @@ const moment = require('moment'); |
3 | 3 | ||
4 | 4 | ||
5 | exports.generateQrCode_prescribe = async ({ medicine, dosage, patientId, doctorId }) => { | 5 | exports.generateQrCode_prescribe = async ({ medicine, dosage, patientId, doctorId }) => { |
6 | - const directory = "/Users/parkkwonsoo/Desktop/Project/Capstone_Design_1/server/data/"; | 6 | + // eslint-disable-next-line no-undef |
7 | + const directory = process.env.QR_DIR; | ||
7 | 8 | ||
8 | const now = moment().format('YYYY-MM-DD_HH:mm'); | 9 | const now = moment().format('YYYY-MM-DD_HH:mm'); |
9 | const qrCodeFileName = `${now}_${doctorId}_${patientId}_${medicine.medicineId}_${dosage}.png`; | 10 | const qrCodeFileName = `${now}_${doctorId}_${patientId}_${medicine.medicineId}_${dosage}.png`; |
10 | 11 | ||
11 | try { | 12 | try { |
12 | await QrCode.toFile( | 13 | await QrCode.toFile( |
13 | - directory + qrCodeFileName, | 14 | + directory + '/' + qrCodeFileName, |
14 | `${medicine.name}/${medicine.medicineId}/${dosage}/${patientId}/${doctorId}`, | 15 | `${medicine.name}/${medicine.medicineId}/${dosage}/${patientId}/${doctorId}`, |
15 | { | 16 | { |
16 | color : { | 17 | color : { | ... | ... |
This diff could not be displayed because it is too large.
-
Please register or login to post a comment