owned this note
owned this note
Published
Linked with GitHub
# mask
## 認領區
- 抓資料 script: @secminhr
- [前端](https://hackmd.io/4Nhes_ZHQ0y_f9Kc8Ug55A): @t510599
- firebase: @a91082900 & @secminhr
## Repo
https://github.com/stoneapptech/mask-frontend
https://github.com/stoneapptech/mask-backend
https://github.com/stoneapptech/mask-data
https://github.com/stoneapptech/mask-utils
## Feature
- 請使用者輸入身分證尾數(0是偶數)
- 使用者可登錄同一鄉/鎮/市/區中的數間藥房(僅一鄉/鎮/市/區)
- push notification
- 藥局開賣前?分鐘通知
## Implementation
- fcm
- fcm topic 以 鄉/鎮/市/區 分(共 371 個)
- 整理各鄉/鎮/市/區有口罩藥局的醫事機構代碼,送到前端
- 前端從收到的 list 裡面篩選使用者登錄的藥房
- 若有,判身分證和星期幾,再發出通知 (Notification API)
- 沒有,不做事
- 需要後端接收前端來的 token 送到 firebase
- service worker
- ~~localStorage 存選擇的藥局清單~~
- service worker 拿不到
- IndexedDB
- 後端
- crontab
- 每半小時戳 script 抓資料
- 資料處理
- /register
- endpoint: https://us-central1-mask-7f3e4.cloudfunctions.net/register
- request: token & area_id & is_even
- 接收新用戶 token & area_id 然後註冊 fcm
- data format:
```json
{
token: string,
area_id: string,
is_even: boolean
}
```
- return value:
- succeed
```json
{
succeeded: true
}
```
- failed due to invalid area id
```json
{
succeeded: false,
message: 'invalid argument'
}
```
- failed while registering fcm
```json
{
succeeded: false,
message: 'subscription failed',
errors: error messages from firebase
}
```
For ```errors``` property, see [Firebase document](https://firebase.google.com/docs/reference/admin/node/admin.messaging.MessagingTopicManagementResponse.html?authuser=0#errors).
- /update
- endpoint: https://us-central1-mask-7f3e4.cloudfunctions.net/update
- request: old_area & token & new_area & is_even
- 接收舊用戶 old_area & token & new_area 然後更新 fcm
- data format:
```json
{
token: string,
old_area: string,
new_area: string,
is_even: boolean
}
```
- return value:
- succeed
```json
{
succeeded: true
}
```
- failed due to invalid area id
```json
{
succeeded: false,
message: 'invalid argument'
}
```
- failed while unregistering fcm
```json
{
succeeded: false,
message: 'unsubscription failed',
errors: error messages from firebase
}
```
- failed while registering fcm
```json
{
succeeded: false,
message: 'subscription failed',
errors: error messages from firebase
}
```
For ```errors``` property, see [Firebase document](https://firebase.google.com/docs/reference/admin/node/admin.messaging.MessagingTopicManagementResponse.html?authuser=0#errors).
- /unregister
- endpoint: https://us-central1-mask-7f3e4.cloudfunctions.net/unregister
- request: token & area_id & is_even
- 接收舊用戶 token & area_id 然後退出 fcm
- data format:
```json
{
token: string,
area_id: string,
is_even: boolean
}
```
- return value:
- succeed
```json
{
succeeded: true
}
```
- failed due to invalid area id
```json
{
succeeded: false,
message: 'invalid argument'
}
```
- failed while unregistering fcm
```json
{
succeeded: false,
message: 'unsubscription failed',
errors: error messages from firebase
}
```
For ```errors``` property, see [Firebase document](https://firebase.google.com/docs/reference/admin/node/admin.messaging.MessagingTopicManagementResponse.html?authuser=0#errors).
## Data
- 為縣市與鄉鎮市區建立 ID
- \<area_id\> = \<City\.Town\>
- Example: `臺北市(A) 大同區(01) = A.01`
- 縣市用身分證英文字母 鄉鎮市區建立流水號
- 醫事機構代碼
- \<code\>
- Example: `5901012061`
- API endpoint (?) https://stoneapptech.github.io/mask-data/
- folder structure
- mask-data/ (host on github.io, update by git push)
- area/
- $area_id.json (此區域中有哪些藥局)
- ```
{
city: "臺北市"
town: "大同區"
store: [
{name: "範例藥局1", address: "某市某區某路", tel: 0212345678, code: 5901012061},
{name: "範例藥局2", address: "某市某區某某路", tel: 0212345679, code: 5901012062}
]
}
```
- store/
- $code.json (藥局資料 p.s. 不用經緯度)
- ```
{
area_id: "A.01"
city: "臺北市",
town: "大同區",
name: "範例藥局1",
address: "某市某區某路",
tel: 0212345678,
note: "備註"
}
```
- area_available
- $area_id.json
- `[5901012061, 5901012062] # 醫事機構代碼`
- mask_number/
- $code.json (各藥局口罩庫存)
- `{adult: 10, child: 10}`
- update_time.txt (後端抓資料的時間)
- `<unix timestamp>`
- area_id.json (https://file.stoneapp.tech/area_id.json)(https://stoneapptech.github.io/mask-data/area_id.json)
- ```
{
"A": {
name: "臺北市",
town: {
"01": "大同區",
...
}
},
"B": {
name: "臺中市",
town: {
"01": "X區",
...
}
},
...
}
```
### 推送的 data
```
{
area_id: "<area_id>"
available: [1234567890,1234567892,1234567894]
}
```
## 流程
- 設定 (Frontend)
```flow
st=>start: 第一次進入
e=>end: 設定完成
digit=>operation: 詢問身分證最後碼
area=>operation: 選擇區域 (縣市 & 鄉鎮市區)
stores=>operation: 選擇藥房 (此區域內的數間)
ask=>condition: 詢問是否開啟通知
register=>operation: 註冊 fcm
(傳送area_id & token)
st->digit->area->stores->ask
ask(yes)->register->e
ask(no)->e
```
- 更新資料 (backend)
```sequence
Server->Open Data: 取得口罩數量
Open Data->Server: 回傳口罩數量
Server-->>github: 上傳更新口罩數量
Server-->>Client: 區域中有口罩藥房清單,依使用者登錄之區域推送
Client->github: 取得詳細數量
```
## Links
### Open Data
https://data.nhi.gov.tw/Datasets/DatasetResource.aspx?rId=A21030000I-D50001-001
### API 參考
https://api.maskhelp.info/swagger-ui.html
### 鄉鎮市區清單
https://www.post.gov.tw/post/internet/Postal/index.jsp?ID=208
### 藥局地址
https://file.stoneapp.tech/%E5%81%A5%E4%BF%9D%E7%89%B9%E7%B4%84%E9%86%AB%E4%BA%8B%E6%A9%9F%E6%A7%8B-%E8%97%A5%E5%B1%80_%E8%97%A5%E5%B1%80.csv
把地址帶有`?`的補齊了
### 整理串
https://g0v.hackmd.io/@kiang/mask-info
https://github.com/kiang/
https://github.com/WJWang/mask-help-info-api/issues/2
### 技術筆記
https://www.sentinelstand.com/article/device-group-management-with-firebase-cloud-messaging
https://firebase.google.com/docs/cloud-messaging/js/topic-messaging
https://developers.google.com/web/updates/2015/12/background-sync