# 送餐機器人畢業專題 ## 必做:環境初始化 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 ``` ![](https://i.imgur.com/9hqFNxW.png) * ### 綁定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 ``` ![](https://i.imgur.com/6xGVHXx.png) * #### 建立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 ``` ![](https://i.imgur.com/nQC3UQi.png) * #### 查詢訂單:根據時間排序 ``` 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資料}