# 送餐機器人畢業專題
## 必做:環境初始化
1. ### 請先在/web/config.json裡面設定軟硬體運行的ip及port
2. ### 設定資料庫資訊:
#### 請在路徑"C:\"下新增"rescarDB.txt":
`"C:\rescarDb.txt"`
```
rescarDb.txt內容如下:
{"dbpwd":"填入資料庫密碼(參閱群組記事本)"}
```
##
## 先在你要放檔案的位置使用以下指令以下載專題資料夾
git clone https://github.com/Liuming9124/rescar.git
cd "剛剛的資料夾名稱"
## Neo4j 自學資訊
* https://ithelp.ithome.com.tw/articles/10242343
* https://neo4j.com/developer/javascript/ (字典 -> 有任何函式不懂可以來這裡查)
* https://ithelp.ithome.com.tw/users/20092912/ironman/3834 -> (Day27 簡易字典!!!)
* https://ithelp.ithome.com.tw/users/20130217/ironman/3541
* https://www.npmjs.com/package/neo4j-driver?activeTab=readme
## Fastapi 自學資訊
* https://fastapi.tiangolo.com/zh/tutorial/
## 點餐系統環境建置
### 1. 需有 npm 環境 (for nodejs)
### 2. 透過 npm install 下載以下packages
#### 由於需要將網頁資料放在web資料夾裡 請先將當前位置改到web裡面,請下指令
"cd web"
#### 接下來透過以下指令安裝模組
"npm install"
#### 模組詳細資料請見/web/package.json
### 3. 執行以下指令將網頁開啟
"nodemon server.js"
if nodemon not found -> "npm install -g nodemon"
-g means global
#### 透過網址以造訪頁面
localhost:7000/home
#### 要進去點餐頁面請先生成桌號代碼,生成QR碼之後點擊QR碼即可開始點餐
##### http://localhost:7000/qrchoose
## Neo4j 資料庫搭建
### 常用指令:
* ### 建立節點:
* n:變數名稱
* lable:標籤(通常都用標籤查詢資料)
* (key,value):節點相關的資料會用此方法儲存
* <mark>注意:每次下指令時會有許多變數,請勿將變數名稱重複使用!!!</mark>
* 每個小括號內放一個Node,若要一次使用多個請用逗號隔開
```
create (n:lable1{key:'value'})
create (n2:lable2{key1:'value',key2:'value2'})
create (t1:'l1'), (t2:'l2'), (t3:'l3')
```
* ### 建立關係
* #### create (node1)-[rel:'關係']->(node2)
* 思考方式:
* A與B有關係 A->B,但是只有箭頭不足以表示關係為何,因此我們要為關係命名
* #### <mark>A-[關係變數名稱:'like']->B</mark>
* 因此我們可以知道A與B的關係為A喜歡B
```
match(第一組節點:l1), (第二組節點:l2)
create (第一個節點)-[變數名稱:'關係名稱']->(第二組節點)
```
* ### 查詢NODE
* 語法: <mark>match (var:type{key:'value'}) return var</mark>
```
查詢所有節點
match(n) return(n)
一次查詢兩組節點
match(n1:t1),(n2:t2{k1:'v1'})
return n1, n2
透過關係查詢節點
match(n1:t1)-[rel:'like']->(n2:t2{k1:'v1'})
return n1, rel, n2
```
* ### NODE進階查詢
```
透過neo4j查詢node會回傳以下格式:
Node {
identity: Integer { low: 75, high: 0 },
labels: [ 'order' ],
properties: { time: 'Sun Mar 26 2023 17:34:45 GMT+0800 (台北標準時間)', status: '0' },
elementId: '4:b36e673b-2419-44d0-abfc-81af86d3f09d:75'
}
```
#### 透過elementId可進行查詢:
##### (1)
```
需要注意的是,elementId屬性並不是Neo4j中的內建屬性,因此不能直接在Cypher查詢中使用。因此,在上面的示例中,我們需要將elementId屬性的值解析為Element ID,並將其傳遞給id()函數。
在上面的示例中,我們使用split()函數來解析Element ID的值,並從中獲取Element ID。然後,我們使用toInteger()函數將Element ID轉換為整數,並將其傳遞給id()函數進行匹配。
最後,我們使用RETURN子句返回匹配到的節點。在這個例子中,節點的屬性和標籤沒有在查詢中使用,因此返回的節點將包含所有屬性和標籤。
```
```
MATCH (n)
WHERE id(n) = toInteger(split('4:b36e673b-2419-44d0-abfc-81af86d3f09d:77', ':')[2])
RETURN n
```
##### (2) 直接將回傳值進行轉換
```
var elementId = record.get('n').elementId = '4:b36e673b-2419-44d0-abfc-81af86d3f09d:77'
eleId = parseInt(elementId.split(':')[2]);
```
* ### 刪除NODE時也刪除連帶關係
```
match(n:lable{key:'value'})
detach delete n
```
* ### 刪除特定NODE
```
match(n) where ID(n)=300 delete (n)
```
* ### 找出特定類別(test)的節點,該節點與其他節點沒有relation(可用於刪除特定沒用到的資料)
```
MATCH (n:test {category: 'test'})
WHERE NOT (n)--()
RETURN n;
```
## 本資料庫使用指令
* ### 創建主節點Menu
`create(n:menu{name:'menu'})`
* ### 創建類型
`Create (:type {name:'壽司'}),(:type{name:'拉麵'}),(:type{name:'刺身'}),(:type{name:'定食'}),(:type{name:'甜點'})`
* ### 建立主節點menu與類型type的關係
```
match(n:menu),(t:type)
CREATE (n)-[p:has]->(t)
return p
```

* ### 綁定type與item的關係:從壽司開始
* merge:先查看node使否存在,若否則建立,若是則查詢
* 創建眾多節點時,可以透過Unwind將多項資訊包裝在一起並用As建立別稱
### <mark> 使用unwind時必須結合【with】使用,為固定用法,否則會報錯 </mark>
```
merge(n:type{name:'壽司'})
with n
UNWIND [
{name: '綜合壽司', price: 180, description:'xxx', image:'food1.jpg'},
{name: '鮭魚壽司', price: 200, description:'xxx', image:'food1.jpg'},
{name: '鮪魚壽司', price: 200, description:'xxx', image:'food1.jpg'},
{name: '干貝壽司', price: 300, description:'xxx', image:'food1.jpg'},
] AS p
CREATE (i:item) SET i = p
CREATE (n)-[:own]->(i)
RETURN n, i
```

* #### 建立QRcode對應URL的關係
```
建立url資料 status:0->可以點餐, 1->已結帳且無法點餐
create(n:url{link:'網址後綴碼',time:'入座時間',table:'桌號',status:0})
```
* #### 新增訂單
* status:狀態(下訂、製作中、待配送、待結帳、已結帳)
* status == 0 1 2 3 4
```
match (n:url{link:'y1tnmwil24'})
create(o:order{time:'now', status: 0})
create (n) -[:order]-> (o)
with o
UNWIND [
{name: '綜合壽司', price: '11', amt:'1', status:'0'},
{name: '鮭魚壽司', price: '11', amt:'1', status:'0'},
{name: '鮪魚壽司', price: '11', amt:'2', status:'0'},
{name: '干貝壽司', price: '11', amt:'1', status:'0'}
] AS carts
CREATE (c:cart) SET c = carts
CREATE (o)-[:orders]->(c)
RETURN o,c
```

* #### 查詢訂單:根據時間排序
```
match(u:url{link:''})-[:order]->(o:order)
return (o)
ORDER BY o.time DESC
```
* #### 根據訂單查詢訂單明細
```
match(o)
where ID(o) = 70
match(o) -[:orders]-> (p:cart)
return p
```
* #### 查詢時間在特定區間內的訂單資料
```
MATCH (o:order) WHERE o.time >= ('2023-04-05-05-27-16.569Z') AND o.time < ('2023-04-22-11-42-05.051Z') RETURN (o) order by o.time desc
```
* #### 查詢目前響服務鈴的客戶桌號
```
MATCH (n:url{alert: "0"})
RETURN n.table
```
* #### 客戶發起服務鈴
```
MATCH (n:url{link: "${req.session.seed}"}) set n.alert='1'
```
* #### 商家完成服務鈴
```
MATCH (n:url{table:'${table}',alert:'1'}) set n.alert='0'
```
* #### 結帳
```
match (n:url{table:'${req.params.table}',status:0})-[r:order]->(o)
set n.status=1 ,o.status=4 return n,o
```
## 硬體:
https://fastapi.tiangolo.com/zh/tutorial/
### 請先參考fastapi的tutorial將環境先建置完成
### 如果沒看上面的tutorial,一定要安裝的:
```
pip install fastapi
pip install "uvicorn[standard]"
```
### 運行fastapi
#### 1.先進入到/hardware的資料夾
```cd /hardware```
#### 2.啟動fastapi指令: --host 機器人IP位址 --port 機器人開放post --reload 程式碼有修正會自動重啟
* #### note: 127.0.0.1 代表本機,可以在自己的電腦上先測試,若要進行遠端控制請配置一個區網下的真實IP才可以進行遠端連線。
```uvicorn main:app --host 127.0.0.1 --port 8000 --reload```
## logs
### 1. 軟硬體logs紀錄
#### 有兩筆logs,分別放在:
* /web/logs.txt
* /hardware/logs.txt
### 2. logs 整合
#### 檔案放在/rescar/checkLogs.py,執行該程式碼後logs會整合web及hardware的logs並打印出來以供參考,方式採用read,不會出現搶占硬體資源的情況。
#### 待處理 :
* 每一秒鐘就再次查詢logs是否有新的資料,若是有新的資料則會打印出新的資料到終端機。
* 格式及目的需要再更詳細且精準
* 可參考資料: https://enochliu.pixnet.net/blog/post/46671816
* 可以建立一個GUI來查看logs
* 目前格式定義: [時間]{JSON資料}