**MapTalk 操作手冊**
數位地圖(digital map)將視覺表示 (虛擬物件;cyber representation) 映射到現實世界中的實體物件(physical objects), 並允許使用者通過其虛擬表示與這些實體物件進行互動。但是創建地圖應用程式通常需要大量的程式設計工作。MapTalk 是一個由網頁應用程式實作視覺化地圖平臺。該平台允許使用者通過其在視覺地圖中的虛擬表示與實體物件進行互動。
<font color="blue">在"MapTalk 3.0"中,我們增加了"**自定義地圖(self-defined map)**"的功能,使用者能夠以自己的圖片作為地圖類型來新增自訂的地圖。透過這個"self-defined map",使用者可以創造出Google Maps提供的預設地圖類型(roadmap)所無法涵蓋的場景,例如大樓室內樓層圖、醫院病房以及公園設施。這種擴增的功能不僅提供了更多地圖類型的選擇,也讓使用者能夠更細緻地呈現特定場景的地圖內容。藉由"MapTalk 3.0",使用者可以更加靈活地探索各種不同的地圖應用場景。</font>
本操作手冊包括兩部分,<font color='flower'>分別為 MapTalk4.0 的安裝與操作。其中對於對接至 IoTtalk v1 或是 v2 來說, 其實作流程大致相同。
註:MapTalk4.0在對接至IoTtalk v1的內容是更新過的,更新過的版本可以選擇使用HTTP或MQTT的連接方式(以前的沒有MQTT),在我的論文中其版本名稱稱作 IoTtalk v3,然後下面操作的內容所謂的 IoTtalk v1皆是指IoTtalk v3</font>
## 第一章 MapTalk安裝流程
- 軟體系統需求
- Ubuntu
- Python 3.6.1+
- MySQL server
- One Unused Port
- Google Maps Platform API Key
- <font color="blue">GDAL</font>
- Python Package Requirements
- Flask
- Flask-HTTPAuth==3.2.1
- Flask-SocketIO==3.1.0
- Flask-SQLAlchemy==2.3.2
- gevent
- PyMySQL==0.9.2
- requests
- SQLAlchemy==1.2.14
- python-engineio==3.2.2
- python-socketio==3.1.1
- Werkzeug==0.16
- pyproj
- Shapely
- markupsafe==2.0.1
- <font color="blue">gdal==3.4.3</font>
- <font color='flower'>IoTtalk v2 Requirements
- iottalk-py==2.3.1</font>
:::warning
請使用virtual environment安裝
:::
### Step 0. 確認IoTtalk v1有開啟dynamic_device_feature_change
到iottalk-v1/lib/SpecialModel.py中將enable_dynamic_device_feature_change設為True
### Step 1. 將 Map clone 下來,並進入Map程式所在目錄
:::warning
<font color="blue">在2022年後,因為gitLab停用, project移植到github</font>
:::
```
git clone https://github.com/IoTtalk/map.git
cd map
git checkout maptalk_v2
git checkout maptalk_new //v1 update
(請先切換分支, 尚未合併至main)
```
<font color='flower'>註:因為在 MapTalk4.0 中 IoTtalk V1.5 稱 IoTtalk V3,所以 MapTalk4.0 分支其實就只是把 maptalk_new 的變數名稱改變了而已。若還不太熟悉版本名稱的話,可以先以 maptalk_new 為主,之後在換成MapTalk4.0 的分支即可。</font>
### Step 2. 申請及啟用Google Maps Platform API Key
2-1. 申請API Key操作請參照以下官方網頁說明,**使用此API需啟用帳單帳戶**(依循[此網址](
https://cloud.google.com/maps-platform/?_ga=2.245439236.1257909505.1615941658-1646089397.1600160341#get-started)步驟可啟用帳單帳戶)。如果使用流量在Google所設定的門檻之內(200美金/月),則可以免費使用此服務;反之,若超過設定門檻則Google會依據使用到的流量進行收費。官方網址如下:
英文版網頁:https://developers.google.com/maps/documentation/javascript/get-api-key
中文版網頁:https://developers.google.com/maps/documentation/android-sdk/get-api-key?hl=zh-tw#restrict_key
[2023 - Google 地圖平台申請教學:](https://furtive-riverbed-673.notion.site/Google-347d5bb35e864e2982c85fc268485707)<font color='flower'>新版的Google地圖平台申請教學!</font>
2-2. 在Google Developers Console中啟用所需的API
- Maps JavaScript API
- Directions API
- Places API
2-3. 用編輯器修改ServerConfig.py裡GoogleMapAPIKey
```
GoogleMapAPIKey = 'YOUR_API_KEY'
```
:::info
詳細申請方式
1. 點選中文版網址,會進入此頁面,點選 "前往憑證頁面"

2. 選擇建立專案,並輸入專案名稱

3. 選擇 "資料庫",並輸入所需要API(例如:Places API)


4. 選擇 "啟用"

5. 啟用完後葉面會被重新導向,點選 "API"

6. 在 "其他API"的地方選擇所需API,最後開啟完所需API的結果如下

7. 點選目錄來選擇 "憑證"

8. 選擇 "建立憑證",再選擇 "API金鑰"

9. 選擇 "限制金鑰"

10. 勾選所需的API

11. 限制金鑰設定完成如下圖

12. 接著就能取得API金鑰

:::
### Step 3. 安裝所需Python Packages 以及 <font color="blue">Linux系統軟體 (必要時用sudo)</font>
<font color="blue">3-1 ~ 3-3建議系統:Ubuntu 20.04以上; 3-4 ~ 3-5建議系統: Ubuntu 20.04以下</font>
<font color="blue">3-1. **(Ubuntu版本>20.04)** 安裝GDAL Linux軟體
(Ubuntu20.04以下apt-get方法僅支援到GDAL 2.4.0版,而MapTalk3.0需使用GDAL>3.1, 因此若Ubuntu版本過舊,建議使用3-4 conda環境安裝.)
- 使用apt-get 安裝
`
sudo add-apt-repository ppa:ubuntugis/ppa
`
`
sudo apt-get update
`
`
sudo apt-get install gdal-bin
`
`
sudo apt-get install libgdal-dev
`
- 檢查是否成功安裝
`
gdalinfo --version
`
- 執行grant_gdal_version.sh,來將gdal對應的python套件版本加到map-requirements.txt
`
./grant_gdal_version.sh
`
</font>
3-2. 建議使用Virtual Environment
- 建立方式 `virtualenv -p python3.8 YourVenvName`
- 啟動方式 `source YourVenvName/bin/activate`
- 關閉方式 `deactivate`
3-3. (**進入Virtual Environment中執行**)在Map資料夾下安裝
- 使用pip軟體包管理系統安裝 Python packages
`
source YourVenvName/bin/activate //進入virtual environment
`
`
pip3 install -r map-requirements.txt //安裝packages
`
- <font color="blue">以下為 map-requirements.txt 檔案內容</font>
```
Flask
Flask-HTTPAuth==3.2.1
Flask-SocketIO==3.1.0
Flask-SQLAlchemy==2.3.2
gevent
PyMySQL==0.9.2
requests
SQLAlchemy==1.2.14
python-engineio==3.2.2
python-socketio==3.1.1
Werkzeug==0.16
pyproj
Shapely
markupsafe==2.0.1
iottalk-py==2.3.1
gdal==`your gdal version`
```
<font color="blue">3-4. **(Ubuntu版本<20.04)** 使用conda安裝GDAL
- 下載並安裝miniconda (或anaconda3):
`
wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh
`
`
chmod +x Miniconda3-latest-Linux-x86_64.sh
`
`
./Miniconda3-latest-Linux-x86_64.sh (依照提示輸入:ENTER yes ENTER yes)
`
- 安裝成功後,source環境變數:`source ~/.bashrc`
- 建立一個conda環境:`conda create --name YourVenvName python=3.8`
- 啟動環境:`conda activate YourVenvName`
- 安裝GDAL: `conda install gdal (依照提示輸入:y)`
- 檢查是否成功安裝: `gdalinfo --version (版本需>3.1)`
</font>
<font color="blue">3-5. **(Ubuntu版本<20.04)** 在同一個conda環境下安裝python套件
- 進入Map資料夾下安裝python套件: `pip3 install -r map-requirements.txt`
</font>
### Step 4. 安裝及設定MySQL server
4-1. 安裝MySQL server
`sudo apt-get install mysql-server`
- 輸入自訂密碼兩次
4-2. 更改MySQL Config
- 用編輯器修改 /etc/mysql/mysql.cnf
`sudo rvim /etc/mysql/mysql.cnf`
- 在mysql.cnf新增以下設定
```
[mysqld]
user = mysql
init_connect = 'SET collation_connection = utf8_bin'
init_connect = 'SET NAMES utf8'
character-set-server = utf8
collation-server = utf8_bin
sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
```
:::info
若 mysql 版本在 8.0 以上,最後一行的 `sql_mode` 請改為
```
sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION
```
:::
4-3. 重新啟動MySQL server
```
sudo service mysql stop (or sudo systemctl stop mysql)
sudo service mysql start (or sudo systemctl start mysql)
```
4-4. 以root身份登入MySQL server
```
sudo mysql -u root -p
```
4-5. (按不同情境選擇操作步驟)建立一個名為map的database,新增一組user及password,並給予該user權限存取名稱為map的database
:::success
- 情境一:MySQL server與Map程式所在主機相同
```
create database YOUR_DB_NAME;
create user 'YOUR_USERNAME'@'localhost' identified by 'YOUR_PASSWORD';
grant all privileges on YOUR_DB_NAME.* to YOUR_USERNAME@'localhost';
exit
```
例如:
```
create database map;
create user 'iottalk'@'localhost' identified by 'iottalkpwd';
grant all privileges on map.* to iottalk@'localhost';
exit
```
:::
:::info
- 情境二:MySQL server與Map程式所在主機不同
```
create database map;
grant all privileges on *.* to 'YOUR_USERNAME'@' YOUR_MAP_SERVER_IP' identified by 'YOUR_PASSWORD';
flush privileges
exit
```
例如:
```
create database map;
grant all privileges on *.* to 'iottalk'@' 140.113.111.111' identified by 'iottalkpwd';
flush privileges
exit
```
- 取消MySQL bind-address
- 用編輯器修改/etc/mysql/mysql.conf.d/mysqld.cnf
`sudo vim /etc/mysql/mysql.conf.d/mysqld.cnf`
- 將mysqld.cnf中的bind-address註解
`#bind-address = 127.0.0.1`
- 重新啟動MySQL server
```
sudo service mysql stop (or sudo systemctl stop mysql)
sudo service mysql start (or sudo systemctl start mysql)
```
:::
4-6. (按不同情境操作)用編輯器修改ServerConfig.py檔案
:::success
- 情境一:MySQL server與Map程式所在主機相同
```
DatabaseURL = 'mysql+pymysql://YOUR_USERNAME:YOUR_PASSWORD @localhost/YOUR_DB_NAME?charset=utf8'
```
例如:
```
DatabaseURL = 'mysql+pymysql://iottalk:iottalkpwd@localhost/map?charset=utf8'
```
:::
:::info
- 情境二:MySQL server與Map程式所在主機不同
```
DatabaseURL = 'mysql+pymysql://YOUR_USERNAME:YOUR_PASSWORD @ YOUR_MySQL_SERVER_IP:3306/YOUR_DB_NAME?charset=utf8'
```
例如:
```
DatabaseURL = 'mysql+pymysql://iottalk:iottalkpwd @ 140.113.111.112:3306/map?charset=utf8'
```
:::
### Step 5. 設定Map Server Port (預設為port 8866)及欲連結的IoTtalk Server
<font color='flower'>5-1. 用編輯器修改ServerConfig.py內的Map Server Port, IoTtalk_V1 Server IP, IoTtalk_V2 Server IP</font>
```
Map Server Port:MapServerPort = "YOUR_MAP_SERVER_PORT"
IoTtalk_v1 Server:IoTtalkIP = 'IOTTALK_V1_SERVER_DOMAIN_NAME'
IoTtalk_v2 Server:IoTtalkIP2 = 'IOTTALK_V2_SERVER_DOMAIN_NAME'
```
例如:
```
Map Server Port:MapServerPort = "8866"
IoTtalk Server:IoTtalkIP = 'https://test.iottalk1.tw'
IoTtalk Server:IoTtalkIP2 = 'https://test.iottalk2.tw'
```
5-2. 設定Map登入管理頁面時的帳號密碼,用編輯器修改ServerConfig.py內的users
```
users = {
"USERNAME":"PASSWORD",
}
```
例如:
```
users = {
"iottalk":"iottalkadmin",
}
```
### <font color="blue">Step 6. 設定Maptile 資料夾
6-1. 在static/底下新增一個資料夾 `mkdir 'YOUR_FOLDER_NAME'`
例如:`mkdir maptile`
6-2. 用編輯器修改ServerConfig.py的 maptile
```
maptile='YOUR_FOLDER_NAME'
```
例如:
```
maptile='maptile'
```
</font>
### Step 7. 設定Default Map Center
7-1. 用編輯器修改static/web_config.js內載入Map時預設的中心點經緯度
```
var default_map_center = {
lat: DEFAULT_CENTER_LATITUDE,
lng: DEFAULT_CENTER_LONGITUDE
};
```
例如:
```
var default_map_center = {
lat:24.7895711,
lng:120.9967021
};
```
### Step 8. 設定Map Video Streaming Server
8-1. 用編輯器修改static/map-cam/js/scripts.js內的Streaming Server IP and Port
```
var ADDR_KURENTO_SERVER = "STREAMING_SERVER_DOMAIN_NAME";
var PORT_KURENTO_SERVER = " STREAMING_SERVER_PORT";
```
例如:
```
var ADDR_KURENTO_SERVER = "video.iottalk.tw";
var PORT_KURENTO_SERVER = "8843";
```
8-2. 若Streaming Server是no secure connection (http),則需用編輯器修改static/map-cam/js/scripts.js名為args.ws_uri變數,將其中的wss改為ws
```
args.ws_uri = 'ws://' + ADDR_KURENTO_SERVER + ':' + PORT_KURENTO_SERVER + '/kurento';
```
### Step 9. 如果Map是no secure connection (http),需修改socket.io路徑
<font color="blue">9-0. https憑證申請方法參考: https://hackmd.io/L9v2K8CoThCsb-AI9ooDfQ?view
若使用secure connection,不需修改socket.io路徑
</font>
9-1. 用編輯器修改static/web_config.js名為socket的變數
```
var socket = io.connect('http://'+location.hostname+': YOUR_MAP_SERVER_PORT/hpc');
```
例如:
```
var socket = io.connect('http://'+location.hostname+':8866/hpc');
```
### Step 10. 如果有搭配Nginx網頁伺服器,需設定Proxy Server
10-1. 用編輯器修改Nginx default configuration file
```
sudo rvim /etc/nginx/sites-available/default
```
- 在server內新增以下路徑
```
location /map/ {
proxy_pass http://localhost: YOUR_MAP_SERVER_PORT /;
proxy_set_header Host $host;
}
location /static/ {
proxy_pass http://localhost: YOUR_MAP_SERVER_PORT /static/;
proxy_set_header Host $host;
}
location /secure/ {
proxy_pass http://localhost: YOUR_MAP_SERVER_PORT /secure/;
proxy_set_header Host $host;
}
location /socket.io/ {
proxy_pass http://localhost: YOUR_MAP_SERVER_PORT /socket.io/;
proxy_set_header Host $host;
}
```
例如:(假設填入port:8866)
```
server {
access_log off;
server_name map.iottalk.tw;
location / {
proxy_pass http://localhost:9999;
proxy_set_header Host $host;
}
location /map/ {
proxy_pass http://localhost:8866/;
proxy_set_header Host $host;
}
location /static/ {
proxy_pass http://localhost:8866/static/;
proxy_set_header Host $host;
}
location /secure/ {
proxy_pass http://localhost:8866/secure/;
proxy_set_header Host $host;
}
location /socket.io/ {
proxy_pass http://localhost:8866/socket.io/;
proxy_set_header Host $host;
}
}
```
10-2. 重新啟動Nginx
```
sudo nginx -s reload
```
### Step 11. 若無搭配Nginx網頁伺服器,需修改Map首頁路徑
11-1. 用編輯器修改index.html
```
document.location.href='http://'+location.hostname+': YOUR_MAP_SERVER_PORT ';
```
例如:
```
document.location.href='http://'+location.hostname+':8866';
```
### Step 12. 載入預設應用
12-1. 執行init_db.py (只能下一次,資料會寫入資料庫中)、(**進入VirtualEnv中執行**)
```
source YourVenvName/bin/activate //進入venv中
python3.6 init_db.py //執行指令
```
### Step 13. Tracking設定
13-1. 到/Map/static/ 路徑內確認有passwd_tracking此檔案
可以利用Ubuntu指令進入到Map/static資料夾,輸入pwd
```
$ cd /Map/static
$ pwd // 會印出檔案路徑,將其複製
```
13-2. 將複製的路徑貼到 ServerConfig.py的PasswdTrackingPath變數
<font color='flower'>
13-3. 以下步驟將視您目前所打算執行的 IoTtalk 版本做決定
對於 Map 所綁定的 IoTtalk_V1 Server:
- 確認是否有命名為 Tracking 的 Input Model (若存在 Tracking Input Model,請跳至 Step 13-3-2)
- 註:不要使用原本就有的名字叫做 "Tracking" 的 Model,因為更新過,所以請自己建立一個 Model 取名可叫 "GPSTracking" 之類的。

對於 Map 所綁定的 IoTtalk_V2 Server:
- 確認是否有命名為 Tracking 的Input Model (若存在 Tracking Input Model,檢查 Map Output Model)
- 確認是否有命名為 Map 的 Output Model (若二者皆存在,請跳至 Step 13-3-2)
13-3-1. 建立 Tracking Model, 與 Map Model
建立 Tracking Model:
- IDF選五個parameters,分別為float,float,string,float,string並命名為"GeoData-I"

- Input Model選擇上述的IDF並命名為"Tracking"
建立 Map Model:
- ODF選五個parameters,分別為float,float,string,float,string並命名為"GeoData-O1"

- 重複上述步驟ODF至少要做 GeoData-O1 到 GeoData-O6
13-3-2. 建立一個IoTtalk_V1 的 project.(若是連接至 IoTtalk_V2 請跳至 13-3-3)
</font>
- 將project取為Tracking. (方便識別的名稱)
- 佈署input model (Tracking)和 output model (Map)
- 將Tracking IDF (GeoData-I) 和 Map ODF (Tracking)相連,完成設定

<font color='flower'>
13-3-3. 建立一個IoTtalk_V2 的 project.(若是連接至 IoTtalk_V1 請跳至 13-3-2)
- 將project取為Tracking. (方便識別的名稱)
- 佈署input model (Tracking)和 output model (Map)
- output model (Map)要勾選 GeoData-O1~GeoData-O6
- 將Tracking IDF (GeoData-I) 和 Map ODF (GeoData-O4)相連,完成設定

(註:為何選擇GeoData-O4,先不要兩點做連接,到第step16的時候,進到 screen 的 Map 裡面後,會看到下面框起來的那行,也就是你選擇GeoData-O4的原因)

</font>
### <font color='blue'>Step 14.設定 map/startup.sh 參數
:::success
- 情境一:Ubuntu>20.04, 若使用virtualenv環境
```
ENV_TYPE="virtualenv"
CONDAENV_NAME=""
CONDA_PATH=""
VIRTUALENV_PATH="/home/iottalk/YourVenvName"
:::
:::info
- 情境二:Ubuntu<20.04, 若使用conda環境
```
ENV_TYPE="conda"
CONDAENV_NAME="YourVenvName"
CONDA_PATH="/home/iottalk/miniconda3"
VIRTUALENV_PATH=""
```
:::
</font>
使用virtual environment則修改為
```
python3="/YourPathToVenv/bin/python3"
```
ex. 若virtual environment命名為venv則修改範例為:
```
python3="/home/iottalk/venv/bin/python3.6"
```
### Step 15.到rc.local加入指令,Server重啟時會自動執行
sudo -u **UserName** /**YourPathToStartup**/map/startup.sh
```
sudo -u iottalk /home/iottalk/map/startup.sh
```
### Step 16. 啟動MapServer
<font color='flower'>啟動之前可以至ServerConfig.py的 IoTtalk_version選擇所想要的執行版本
版本預設為1,將啟動 Iottalk_v1 的連結,更改成 2 則切換成 IoTtalk v2 的連結
```
IoTtalk_version = 1
```
選擇版本後,也要在 startup.sh底下的地方,取消要用的 Tracking 版本之註解
選擇 版本1 則打開 58 行的註解,選擇 版本2 則打開 66 行的註解

</font>
執行: (請確認python版本 >= python3.8+)
```
./map/startup.sh
```
完成,會出現在screen map session中(screen 語法)
- $ screen -ls //顯示所有的screen session
- $ screen -r <session neame> //進入此session
- ctrl+方向鍵(左或右) //在seesion中切換不同windows
- ctrl a+d //離開screen session (detach)
詳細請網路查閱
[註]預設有四個應用(Camera, Obstacle, Fence, Tracking),介紹請參閱Appendix
<font color='flower'>
[註] V1 更新的部分在於多了 mqtt 的傳輸方式。
若要使用 mqtt 做溝通的話,要優先去設定SA.py的以下幾行
```python
MQTT_broker = 'class.iottalk.tw' # MQTT Broker address, for example: 'iottalk.tw' or None = no MQTT support
MQTT_port = 5566
MQTT_encryption = True
MQTT_User = 'iottalk'
MQTT_PW = 'iottalk2023'
```
</font>
---
### Appendix
#### 未使用Virtual Environment啟動Map Server (不建議)
1. 進入iottalk_server_1.0 screen(若沒有screen 先建立一個)再往下操作
```
screen -r
```
2. 新增一個screen分頁
```
Ctrl a+c
```
3. 切換至Map程式所在目錄
```
cd iottalk_server_1.0/da/Map
```
4. 執行start_py
```
python3.6 start.py
```
5. 離開screen
```
Ctrl a+d
```
#### Camera應用介紹

功能:可在地圖上顯示來自RTSP串流影像
#### Tracking 設定

功能:可以追蹤使用者,並呈現在地圖上
<font color='flower'>
Step 1. 對於連接 V1 IoTtalk 版本:到 MapTalk 所綁定的 IoTtalk 建立 Tracking Project
Input model為Tracking, Output model為Map

對於連接 V2 IoTtalk 版本:

</font>
Step 2. 進入Tracking網址
URL: https://MapTalk網址/#Tracking
Notice: #後的名稱和App Name有關,例如:在MapTalk上,App命名為Tracking,所以網址#後加入Tracking
- 2-1. 輸入使用者名稱
- 2-2. 輸入連絡電話
- 2-3. 若此時在地圖上沒有出現human的icon,請到Tracking project中確認資料是否有上傳

Step 2. (補充) Andrid Tracking mobile App
- 輸入使用者名稱
- 輸入連絡電話
- 選擇追蹤持續時間
- 勾選是否需要被電子圍籬追蹤
Step 3. 此時使用者只要進出圍籬就會發送通知到Line群組,並且在Map的圍籬內會留下紀錄的點
Step 4. 使用者可以大力搖晃手機來發送Line的緊急訊息 (需設定GoogleAppScript+Line Notify)
#### Electronic Fence設定

功能: 可繪製圍籬並搭配Tracking應用,如果使用者進出圍籬會對管理者發送緊急訊息。
Step 1. (首次安裝免修改)修改ServerConfig.py中Tracking_app_num, Fence_app_num, FenceRecord_app_num的編號
1-1. 進入Map database
```
mysql -u <db_username> -p;
```
1-2. 切換到map所在的database
```
use map;
```
1-3. 查看icon_define_table,並看其app number為何
```
select * from icon_define_table;
```

1-4. 根據icon_define_table中的number來修改ServerConfig.py中的參數
例如:
```
Fence_app_num = 3
Tracking_app_num = 4
FenceRecord_app_num = 5
```
Step 2. (首次安裝免修改)修改/static/web_config.js中FenceTracking_app_num
根據Step 1. icon_define_table中FenceRecord_app_num的編號
```
var FenceRecord_app_num = 5;
```
Step 3. 申請Line Notify Token
教學: https://www.oxxostudio.tw/articles/201806/line-notify.html
3-1. 開啟 LINE Notify 網站
LINE Notify : https://notify-bot.line.me/zh_TW/

3-2. 選擇個人帳戶並點選個人頁面

3-3. 點選發行權杖

3-4. 填寫權杖名稱 (當發送LINE訊息時會出現權杖名稱在每則訊息開頭)

3-5. 選擇發送訊息的聊天室 (一對一聊天室 或 群組)再點選發行

3-6. 複製權杖ID並保存好 (權杖ID只會出現這一次!!!)

3-7. 將權杖貼到 ServerConfig.py
```
token = “YOUR_LINE_TOKEN”
```
Step 4 申請Google Google Apps Script
因為LINE Notify不能單純透過純前端發送訊息,我們透過google Apps Script來佈署網頁應用,當使用者在tracking網頁時可以大力搖晃手機來發送緊急訊息。
- 4-1. 從雲端硬碟中選擇Google Apps Script

- 4-2. 命名專案 (Figure 4.2 (1)) 並將下面的程式碼貼上 (Figure 4.2 (2))

Figure 4.2 Google Apps Script GUI
```
function doPost(e) {
var param = e.parameter;
var msg = param.msg;
UrlFetchApp.fetch('https://notify-api.line.me/api/notify', {
'headers': {
'Authorization': 'Bearer ' +'YOUR_LINE_TOKEN',
},
'method': 'post',
'payload': {
'message':msg
}
});
}
```
- 4-3. 將LINE權杖貼到程式碼 YOUR_LINE_TOKEN中 (Figure 4.2 (3))
- 4-4. 按下"儲存" (Figure 4.2 (4))後,再按下"執行" (Figure 4.2 (5))來要求權限

:::success
✔ 出現此錯誤訊息為正常情形,可繼續進行下一步

:::
- 4-5. 點選"佈署(Deploy)"再點選 "新的佈署"

- 4-6. 選擇 佈署為網頁應用程式


Figure 4.6 佈署介面
- 4.6.1. 輸入描述 (自己看得懂為主) (Figure 4.6 (1))
- 4.6.2. 設定“Execute the app as” 成 自己(Me) (Figure 4.6 (2))
- 4.6.3. 設定“Who has access to the app” 所有人(Anyone) (Figure 4.6 (3))
- 4.6.4. 點選 “佈署(Deploy)”
- 4.7. 複製網路應用程式URL,並保存好

- 4.8. 將網頁URL貼到 /static/web_config.js
```
var GoogleScriptURL = “YOUR_WEB_APP_URL”;
```
Step 5. 在ServerConfig.py設定Map URL,此URL會傳送至LINE訊息中
```
map_url = "YOUR_MAP_URL"
```
Step 6. 重啟Map
Step 7. 搭配Tracking應用
- 7-1. 當使用者進出圍籬,會對3-5.的聊天室發送訊息
- 7-2. 在Tracking網頁時,使用者可以大力搖晃手機對3-1.的聊天室發送緊急訊息。
#### Obstacle應用

功能: 放置obstacles的地方,在routing時會被繞開。
---
## 第二章 MapTalk操作流程
### <font color="blue">[管理頁面 (Admin) ] </font>
### Step 1. 打開瀏覽器進入管理頁面
1-1. 由網址列輸入網址
- 情境1:secure connection (https):
```
https://DOMAIN_NAME/map/admin
```
例如:
```
https://test.iottalk.tw/map/admin
```
- 情境2:no secure connection (http):
```
http://YOUR_IP: YOUR_MAP_SERVER_PORT/admin
```
例如:
```
http://140.113.111.111:8866/admin
```
1-2. 輸入Section 1 Step 5所設定登入Map管理頁面時的帳號密碼
<font color="blue">1-3. 頁面區域介紹
1. Map區域 [本區域為MapTalk3.0 新增之區域] (Figure 18 (1))
2. App區域 (Figure 18 (2))
3. Embedded Google Maps區域

Figure 18. Layout of the web page.
</font>
### <font color="blue">Step 2. 在管理頁面中新增自定義地圖(self-defined map)
* MapTalk3.0 使用Google Maps的roadmap(街景)作為預設地圖,稱為"MapTalk",並且為MapTalk3.0的首頁。
* 在MapTalk頁面中, 由Map drop-down list(Figure 2)來管理Map。
* Map(Figure 19 (1)): Map drop-down list,並且顯示當前地圖的名稱 (例如: MapTalk)。
* MapTalk(Figure 19 (2)): 一個按鈕,點擊返回到首頁。
* Add Map(Figure 19 (3)): 一個按鈕,點擊跳出新增Map設定欄。
* Show All(Figure 19 (4)): 一個按鈕,點擊顯示所有map objects。
* 顯示/修改現有自定義地圖(Figure 2 (5)): 一個按鈕清單,每個按鈕各自顯示其自定義地圖的名稱。點擊按鈕顯示map object以及跳出Map設定欄。

Figure 19. Map drop-down list.
* **新增自定義地圖**
1. 點擊Add Map(Figure 19 (3))
2. 跳出 Map設定欄 (Figure 20)

Figure 20. Map setup bar.
填入以下欄位:
* Name(Figure 20 (2)) 欄位填入地圖名稱,由輸入者自行命名,例如: Dorm3。
* Location(Figure 20 (3)) 欄位可以手動填入經緯度或以點擊地圖(Figure 3 (9))的方式新增此自定義地圖的位置。
* Description(Figure 20 (4)) 欄位可以填入欲顯示在此map object的說明內容,內容可以為純文字與超連結搭配。
* Image(Figure 20 (5))欄位從輸入者端選擇並上傳一張圖片(格式限制: .jpg/.jpeg/.png)作為此自定義地圖的預設Submap,並預設其Submap名稱為"1F"。
3. 點擊"Save"(Figure 20 (6))儲存自定義地圖設定。
4. 等待server 處理完畢,自定義地圖新增完成。
5. 如需修改自定義地圖,點擊對應的自定義地圖按鈕(Figure 19 (5))即會出現Map設定欄,修改完成點擊"Save"(Figure 20 (6))。
6. 如需刪除自定義地圖,點擊對應的自定義地圖按鈕(Figure 19 (5))即會出現Map設定欄,點擊"Delete"(Figure 20 (8))。
* **進入自定義地圖**
1. 點擊欲進入的自定義地圖按鈕(Figure 21 (1)),以"Dorm3"為例,會顯示其map object(Figure 21 (2))。
2. 點擊map object(Figure 21 (2))視窗裡的超連結,跳轉頁面進入自定義地圖。

Figure 21. View the map object.
3. 完成進入自定義地圖的頁面

Figure 22. Self-defined map on the admin page.
</font>
### <font color="blue">Step 3. 在自定義地圖的管理頁面中新增Submap
* 在"MapTalk"主頁中,因為roadmap(街景)圖層不會有不同的樓層或分部,因此我們將其Submap隱藏起來。
* 由主頁點擊map object中的超連結進入自定義地圖頁面時,預設的Submap為"1F"。
* 由Submap drop-down list來管理Submap:
* Submap(Figure 23 (1)): Submap drop-down list,並顯示當前Submap的名稱(例如:1F)。
* Add Submap(Figure 23 (2)): 一個按鈕,點擊跳出新增Submap設定欄。
* 顯示/修改現有的Submap(Figure 23 (3)):一個按鈕清單,每個按鈕各自顯示其Submap的名稱。點擊按鈕跳轉Submap頁面。

Figure 23. Submap drop-down list.
**新增自定義地圖的Submap**
1. 點擊"Add Submap"(Figure 23 (2))
2. 跳出Submap設定欄(Figure 24 (1))

Figure 24. Submap setup bar.
填入以下欄位:
* Name(Figure 24 (2)) 欄位填入Submap名稱,由輸入者自行命名,例如: B1, 南棟2F。
* Location(Figure 24 (3)) 欄位不需填入,與此Map的經緯度位置一致。
* Description(Figure 24 (4)) 欄位可以填入欲顯示在此Submap的說明內容。
* Image(Figure 24 (5))欄位從輸入者端選擇並上傳一張圖片(格式限制: .jpg/.jpeg/.png)。
3. 點擊"Save"(Figure 24 (6))儲存Submap設定。
4. 等待server 處理完畢,Submap新增完成。
5. 如需修改Submap,點擊對應的Submap按鈕(Figure 23 (3))即會跳轉至該Submap頁面,並出現Submap設定欄,修改完成點擊"Save"(Figure 24 (6))。
6. 如需刪除Submap,點擊對應的Submap按鈕(Figure 23 (3))即會跳轉至該Submap頁面,並出現Submap設定欄,點擊"Delete"(Figure 24 (8))。
* 自定義地圖的預設Submap(1F)是不能刪除的,若要刪除,僅能回到主頁刪除整個自定義地圖。
* **切換Submap頁面**
1. 點擊欲切換的Submap按鈕(Figure 23 (3)),以"B1"為例。
2. 進入切換指定的Submap頁面(Figure 25)

Figure 25. Switch to specific Submap.
</font>
### Step 4. 在管理頁面中新增應用
1. 點擊app drop-down menu中的“Add App” (Figure 1 (a))

Figure 1. Application creation and setup.
2. 跳出新增應用設定欄 (Figure 2 (a)-(l))

Figure 2. Application creation and setup (cont.)
- Name (Figure 2 (a)) 欄位要填入的是應用名稱,由輸入者自行命名,例如:WashingMachine。
- Location (Figure 2 (b)) 欄位則是要選擇此應用的屬性為靜態(Stationary)或動態(Movable)。
- Layout (Figure 2 \(c\)) 欄位要選擇的是此應用的layout屬性,共有三種屬性可供選擇。
(1) Picture的選項代表要建立的是picture objects,此時畫面上會pop up出input Picture URL的畫面(Figure 3) ,可嵌入圖片網址以作為此應用的layout。

Figure 3. Picture URL dialog box
(2) No Letter的選項代表layout會是circle (Figure 4 (b))的形狀, 沒有任何縮寫字母會顯示在circle中 或是 Polygon (Figure 4.1 (1))使用者可以自己繪製。

(a)Round rectangle (b) circle \(c\) rounded square
Figure 4. Layouts for geographic shape objects

Figure 4.1 Polygon
(3) Letter(A~Z)的選項代表layout會根據Visual選項的選擇有所差異,以rounded rectangle (Figure 4 (a))或rounded square (Figure 4 \(c\)) 的幾何圖形呈現。
- Value (Figure 2 (g))欄位要選擇此應用的數值呈現方式,共有兩種方式可供選擇。
(1) Text的選項代表layout是以rounded rectangle (Figure 4 (a)) 的形狀呈現。
(2) Color (Figure 2 (i)) 的選項代表此應用的數值要以不同顏色呈現,畫面上就會pop up出input min, max設定range的畫面 (Figure 5),輸入者可以根據此應用會出現的數值範圍進行填寫,而layout的形狀則是rounded square (Figure 4 \(c\))。

Figure 5. Color range dialog box
- Warning 欄位只有在Stationary屬性才會出現,勾選表示此應用從IoTtalk來的屬性變為: Lat(float), Lng(float), Name(String), Status(float), Description(String),其中Status傳0或1,1代表新增icon; 0代表根據Name來刪除icon,Description為icon的info window的內容。勾選後可以根據來自IoTtalk的資料,自動去增刪此應用下的cyber objects。
- Quick Access (Figure 2 (j)) 欄位做勾選表示此應用的按鈕會同時顯示於畫面上方的menu bar (e.g. Figure 1 \(c\))以便快速存取。
3. 點擊“Save”(Figure 2 (k)) 儲存應用設定,應用新增完成。
4. 如需修改或刪除應用設定,直接點擊應用按鈕 (e.g. Figure 1 (b)\(c\)) 即會出現應用設定欄 (Figure 2 (l))。
### Step 5. 新增應用下的Cyber Object (以WashingMachine應用為例)
1. 點擊“Add WashingMachine”(Figure 1 (d))
2. 跳出新增Cyber Object的設定欄 (see Figure 6 (a-c, e, f)).

Figure 6. Cyber object creation and setup
- Name (Figure 6 (a)) 欄位要填入的是此Cyber Object的名稱,由輸入者自行命名。
- Location (Figure 6 (b)) 欄位可使用手動填入經緯度 (Figure 6 \(c\)) 或以點擊地圖(Figure 6 (d))的方式新增此Cyber Object的位置。
- Description (Figure 6 (e)) 欄位可填入欲顯示在此Cyber Object pop up dialog box中的內容,內容可以為純文字與超連結搭配。
3. 點擊“Save”(Figure 6 (f)) 儲存Cyber Object設定,Cyber Object新增完成。
4. 如需修改或刪除Cyber Object設定,直接點擊Cyber Object按鈕即會出現Cyber Object設定欄 (Figure 6)。
若應用屬於動態(Movable)屬性,例如:公車,則可以省略此步驟,因為動態(Movable)應用的Cyber Object在Map上沒有固定位置。
### Step 6. 將實體Sensor連接至MapTalk
1. 前往IoTtalk Homepage -> Project -> Select a project (Figure 7 (a)) -> add project (Figure 7 (b)) 建立自己的project

Figure 7. IoTtalk project window
2. 點擊Model (Figure 8 (a)) -> Map (Figure 8 (b)) 可叫出已註冊的Map device (Figure 8 \(c\))

Figure 8. Device model selection
3. 點擊右方所出現已註冊的Map Device (Figure 8 \(c\)),device model及其device features (DFs) 出現如Figure 9所示。其中DFs (Figure 9 (a))會隨Step 2新增或刪除應用同步動態增減。

Figure 9. Device model connection
<font color='flower'>
3.1 請注意連接iottalk_v2時,因無自動增加功能的原因,所以要手動至 sa.py 檔案中,多給予一個odf,並且在新增應用時也要多勾選一個 odf 例如:GeoData-O7

</font>
4. Map 中每個DF皆有五個參數。由左至右分別是緯度 (Figure 10 (a))、經度 (Figure 10 (b))、名稱 (Figure 10 \(c\))、數值 (Figure 10 (d))、時間戳記 (Figure 10 (e)) ,其中「名稱」欄位需與Step 3所設的Cyber Object名稱對應,而五個參數的型態分別為float、float、string、float、string。值得注意的是,若應用屬於動態(Movable)屬性,例如:公車,則「數值」欄位代表ID,以區別不同的動態(Movable) Cyber Object。

Figure 10. Device model connection (cont.)
5. 此時 input device feature (IDF; Figure 10 (f))可以開始透過Join連線 (Figure 10 (g))傳送資料至作為output device feature (ODF; Figure 10 (h)) 的Map,將每種應用的資料傳送至對應的DF。此外,以右鍵點擊Join Circle即可見Figure 10右方monitor。
6. Map還可以與其它應用搭配使用,像是Message、LineBot,用以傳送異常通知,例如:Figure 11呈現溼度sensors (Figure 11 (a)) 與Message DA (Figure 11 (b))的搭配使用,當錯誤發生時,Message DA便會傳送異常通知給先前有在Message管理網頁填入e-mail或手機的使用者 (Figure 12)。

Figure 11. Map DA combined with Message DA

Figure 12. Message management web page
### <font color="blue">[使用者頁面 (User) ] </font>
### Step 7. 前往一般瀏覽頁面
1. 由網址列輸入網址
- 情境1:secure connection (https)
```
https://DOMAIN_NAME/map
```
例如:
```
https://map.iottalk.tw/map
```
- 情境2:no secure connection (http)
```
http://YOUR_IP: MAP_SERVER_PORT
```
例如:
```
http://140.113.111.111:8866
```
### Step 8. 瀏覽Map GUI
* <font color="blue">**如需要切換至自定義地圖**
0-1. 點擊Map drop-down list中欲切換的自定義地圖按鈕(Figure 26 (1))
0-2. 點擊Map object 中的超連結(Figure 26 (2)),跳轉至指定的自定義地圖頁面。

Figure 26. View the map object on MapTalk user page.
0-3. 完成進入自定義地圖的頁面

Figure 27. self-defined map on user page.</font>
1. 點擊drop-down list (Figure 11 (a)(b))查看各種應用的狀態
- Cyber Object的Layout是按照Step 2應用設定的選擇,共有四種,分別是Picture (Figure 13 \(c\)), Circle (Figure 13 (d)), Round rectangle (Figure 13 (e)) and Rounded square (Figure 13 (f)).
- 此外,Cyber Object可分為兩類:
(1) single-attribute object:以Step 4所說明的方式經由MapTalk接收資料的Cyber Object,如Figure 13 (d)(e)(f)所示。
(2) composite-attribute object:不經由MapTalk,而是在Dialog Box (Figure 13 (g)) 以連結連接至外部的Dashboard、Controllers或 Actuators。

Figure 13. A 2D visual map based on MapTalk
2. 點擊地圖上顯示的Cyber Object會出現Dialog box (Figure 13 (g)),Dialog Box所顯示的內容來自Step 3 Cyber Object Description的設定。
3. Single-attribute object在Dialog Box會顯示Update Time (Figure 14 (a)),可查看最後一次更新的時間,如果距離現在時間已超過一小時,則Cyber Object的外圍會多一圈黑色表示離線 (Figure 14 (b))。

Figure 14. Movable cyber object dialog box
4. 動態(Movable) Cyber Object的Dialog Box會出現History選項 (Figure 14 \(c\)),點擊會出現時間長度選擇視窗(Figure 15),選擇後可追蹤Cyber Object的歷史軌跡 (Figure 13 (h))。

Figure 15. History time selection dialog box
5. 點擊Routing (Figure 13 (i)) 按鈕可規劃避開路障的路徑
(1) 以Step 3的方法在管理頁面點擊Obstacle應用新增Obstacle Cyber Object (Figure 16 \(c\))。
(2) 點擊Routing (Figure 13 (i)) 按鈕,設定完出發點與終點 (Figure 16 (a))後,按下“Start Routing”按鈕 (Figure 16 (b))。
(3) 可以看到路徑 (Figure 16 (d))已避開路障。

Figure 16. Path routing
6. 點擊camera cyber objects (Figure 13 \(c\))可查看攝影機畫面
(1) 以Step 3的方法在管理頁面點擊Camera應用新增camera cyber object (Figure 13 (j)),此時的Description欄位需填入Camera URL。
(2) 新增完camera cyber objects後,可點擊camera cyber object觀看攝影機畫面(Figure 17 (a))。

Figure 17. Video streaming in MapTalk
<font color='flower'>
學會上面介紹後,若對 v2 仍有不太清楚如何操作的話,可以參考以下:</font>
[測試建立 v2 idf 連接至 map 的步驟](https://furtive-riverbed-673.notion.site/v2-idf-map-33668000694b46c2aedafc186fb73ee1?pvs=4)