Compare commits

..
14 Commits
Author SHA1 Message Date
chiyu1468 3f9b2ab8e5 dev v0.61
為了電池子計畫 硬加了一些東西 不太穩定 懶得詳述了
2024-06-02 16:35:53 +08:00
chiyu1468 f937f89e56 dev v0.60
前面的版本是增加控制部分
這個版本是增加從 statusText 弄成電池的 電流與溫度值
該功能可以搭配 test3_vel_gps_bat_head.py 程式測試
2024-04-17 15:51:08 +08:00
chiyu1468 0f532701f2 nothing change
只是整理一下排版跟刪掉多餘註解
2024-03-27 07:15:40 +08:00
chiyu1468 06b9df2c0f basic command complete
使用另一個方式做了 goto
完成了 set height
2024-03-27 07:02:55 +08:00
chiyu1468 55d92d4614 first command online
第一個版本
2024-03-26 23:20:43 +08:00
chiyu1468 49752d4626 Parameter Test
正在提取system的各種資訊
2024-03-05 16:26:23 +08:00
chiyu1468 c9147f4314 stable v0.42
mavone.cpp
    - 修正 status 管理 bug : 還未改變資料庫狀態 就被程式的管理列表刪除
    - 新增 指定本服務於 MAVLink 上的 sysid=197, compid=254 (應該是不會特別去動態調整所以硬寫在裡面)
2024-02-23 17:06:26 +08:00
chiyu1468 37fcd66585 stable v0.41
mavone.cpp
  - 優化mysql中 connect state 寫入
systemHandler.cpp
  - 電量 增加 電量%數 電壓
  - 經緯高 電量 in_air 於實體飛控板傳輸頻率
2024-02-02 15:38:04 +08:00
chiyu1468 98e399cbd5 stable v0.4
- 修正 disconnected 後不斷重刷的問題
- 修正 相同 sysid 再連接會產生抓錯的問題
- 增加 非 autopilot 裝置被 subscribe telemetry 問題
2024-01-13 23:35:04 +08:00
chiyu1468 feb441d2f4 stable v0.3
修正 system id 重複獲取問題
修正 handlerState 卡在 Prologue 問題
2024-01-12 14:20:34 +08:00
chiyu1468 60c8a49b7e stable v0.2
沒有添加新功能,僅調整程式文件結構以利後續開發。

mavone.cpp => 處理主要迴圈與mysql連接
systemHandler.cpp => 處理 mavsdk_server 迴圈
globals.cpp => 宣告全域變數
2023-12-29 17:55:28 +08:00
chiyu1468 57588d5026 for andy debug 2023-12-25 16:46:54 +08:00
chiyu1468 efe5bc4e3c stable v0.1
mavone 是 專案主要程式
unit function dev 是 一些開發時的測試程式

虛擬機系統可以隨時連線與斷連了
把 mysql table schema 備份在 NodeRed_one.sql
2023-12-15 09:37:55 +08:00
chiyu1468 ce0fb7454a The first connection success
第一版把 MAVSDK 的 Telemetry 接上 MySQL 資料庫
額外加了不少的 include
同時也在 CMakeLists 加了 mysqlcppconn 相依庫 (這是 mysql 的官方庫)
但是其中的設定一定會因為環境不同需要修正的
2023-12-14 00:49:06 +08:00
19 changed files with 3110 additions and 358 deletions
+43
View File
@@ -0,0 +1,43 @@
FROM ubuntu:20.04
# HOW TO USE THIS FILE
# 切換到這個檔案的目錄處
# 輸入以下指令
# docker build -t mavone_server:0.XX .
COPY mavone /home/mavone/pkg
COPY LibPack/libmavsdk-dev_1.4.18_ubuntu20.04_amd64.deb /home/mavone/pkg/libmavsdk.deb
RUN test -f /home/mavone/pkg/libmavsdk.deb || (echo "File not found: /home/mavone/pkg/libmavsdk.deb" && exit 1)
RUN apt-get update && apt-get install -y locales && rm -rf /var/lib/apt/lists/* \
&& localedef -i en_US -c -f UTF-8 -A /usr/share/locale/locale.alias en_US.UTF-8
ENV LANG en_US.utf8
ENV CONFIG_FILE /home/mavone/config.txt
RUN apt-get update
RUN apt-get install -y g++ cmake libmysqlcppconn-dev
WORKDIR /home/mavone/pkg
RUN dpkg -i libmavsdk.deb
RUN cmake -Bbuild -H.
RUN cmake --build build
RUN cp build/mavone /usr/local/bin/mavone
WORKDIR /home/mavone
RUN rm -r /home/mavone/pkg
CMD ["/bin/sh", "-c", "mavone $CONFIG_FILE"]
# 測試語句
# docker run -it --rm -e CONFIG_FILE="/home/mavone/mavone_config.txt" -v D:\tryRun:/home/mavone mavone_server:0.60
# docker run -it --rm -e CONFIG_FILE="/home/mavone/mavone_config.txt" -p 14550:14550 -v D:\tryRun:/home/mavone mavone_server:0.60
# docker run -it --rm -e CONFIG_FILE="/home/mavone/config1.txt" -p 49304:49304 -v /home/webpage/Mavsdk_DEV/mavone:/home/mavone mavone_server:0.421
# 這個方式會是錯的 因為會去執行 host 的環境變數 而不是 container 的環境變數
# ENTRYPOINT ["mavone"]
# CMD ["$CONFIG_FILE"]
+384
View File
@@ -0,0 +1,384 @@
<mxfile host="Electron" modified="2024-01-16T09:06:13.081Z" agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/22.1.18 Chrome/120.0.6099.199 Electron/28.1.2 Safari/537.36" etag="rZ2WN5JBLS4L5ICd5Iy6" version="22.1.18" type="device">
<diagram id="C5RBs43oDa-KdzZeNtuy" name="Page-1">
<mxGraphModel dx="2660" dy="1503" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
<root>
<mxCell id="WIyWlLk6GJQsqaUBKTNV-0" />
<mxCell id="WIyWlLk6GJQsqaUBKTNV-1" parent="WIyWlLk6GJQsqaUBKTNV-0" />
<mxCell id="qup03jMZmrsR1gBGYmkV-3" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="qup03jMZmrsR1gBGYmkV-1" target="qup03jMZmrsR1gBGYmkV-2">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-1" value="mavone.cpp" style="ellipse;whiteSpace=wrap;html=1;fillColor=#FFCCCC;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="350" y="10" width="80" height="40" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-5" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="qup03jMZmrsR1gBGYmkV-2" target="qup03jMZmrsR1gBGYmkV-4">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-2" value="Input config file name" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="330" y="80" width="120" height="40" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-29" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="qup03jMZmrsR1gBGYmkV-4" target="qup03jMZmrsR1gBGYmkV-14">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-4" value="Read config file content and parse into&amp;nbsp;&lt;i&gt;&lt;u&gt;initSetting&lt;/u&gt;&lt;/i&gt;&lt;span style=&quot;background-color: initial;&quot;&gt;&amp;nbsp;&lt;/span&gt;" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="330" y="160" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-6" value="subsribe event&lt;br&gt;new MAVSDK::System detect" style="swimlane;whiteSpace=wrap;html=1;startSize=30;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="487" y="270" width="253" height="440" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-9" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="qup03jMZmrsR1gBGYmkV-6" source="qup03jMZmrsR1gBGYmkV-7" target="qup03jMZmrsR1gBGYmkV-8">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-7" value="Get all connect MAVSDK::System list" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="qup03jMZmrsR1gBGYmkV-6">
<mxGeometry x="10" y="40" width="120" height="40" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-11" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="qup03jMZmrsR1gBGYmkV-6" source="qup03jMZmrsR1gBGYmkV-8" target="qup03jMZmrsR1gBGYmkV-10">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-8" value="Contrast the list with &lt;i&gt;&lt;u&gt;systemHandlerInfos &lt;/u&gt;&lt;/i&gt;and pinpoint an object in the list that has a sysid exclusive to it." style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="qup03jMZmrsR1gBGYmkV-6">
<mxGeometry x="10" y="105" width="120" height="75" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-35" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="qup03jMZmrsR1gBGYmkV-6" source="qup03jMZmrsR1gBGYmkV-10" target="qup03jMZmrsR1gBGYmkV-12">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-36" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="qup03jMZmrsR1gBGYmkV-6" source="qup03jMZmrsR1gBGYmkV-10" target="qup03jMZmrsR1gBGYmkV-18">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-10" value="&lt;font style=&quot;font-size: 11px;&quot;&gt;Has an &lt;br&gt;object been &lt;br&gt;discovered?&lt;/font&gt;" style="rhombus;whiteSpace=wrap;html=1;" vertex="1" parent="qup03jMZmrsR1gBGYmkV-6">
<mxGeometry x="35" y="208" width="70" height="66" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-37" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="qup03jMZmrsR1gBGYmkV-6" source="qup03jMZmrsR1gBGYmkV-12" target="qup03jMZmrsR1gBGYmkV-16">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-12" value="Start an &lt;u style=&quot;&quot;&gt;&lt;b&gt;systemHandler&lt;/b&gt;&lt;/u&gt;&lt;span style=&quot;background-color: initial;&quot;&gt;&amp;nbsp;&lt;br&gt;thread for this MAVSDK::System object.&lt;/span&gt;" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="qup03jMZmrsR1gBGYmkV-6">
<mxGeometry x="130" y="204" width="100" height="74" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-46" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="qup03jMZmrsR1gBGYmkV-6" source="qup03jMZmrsR1gBGYmkV-16" target="qup03jMZmrsR1gBGYmkV-45">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-16" value="Record the required information into an&amp;nbsp;&lt;i&gt;&lt;u&gt;handlerInfo&lt;/u&gt;&lt;/i&gt; object." style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="qup03jMZmrsR1gBGYmkV-6">
<mxGeometry x="120" y="290" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-18" value="END" style="whiteSpace=wrap;html=1;" vertex="1" parent="qup03jMZmrsR1gBGYmkV-6">
<mxGeometry x="40" y="390" width="60" height="20" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-23" value="Yes" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" vertex="1" parent="qup03jMZmrsR1gBGYmkV-6">
<mxGeometry x="90" y="210" width="40" height="30" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-24" value="No" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" vertex="1" parent="qup03jMZmrsR1gBGYmkV-6">
<mxGeometry x="35" y="274" width="40" height="30" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-47" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="qup03jMZmrsR1gBGYmkV-6" source="qup03jMZmrsR1gBGYmkV-45" target="qup03jMZmrsR1gBGYmkV-18">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-45" value="Add this handlerInfo object in&amp;nbsp;&lt;br&gt;&lt;i style=&quot;border-color: var(--border-color);&quot;&gt;&lt;u style=&quot;border-color: var(--border-color);&quot;&gt;systemHandlerInfos&lt;/u&gt;&lt;/i&gt;&lt;br&gt;&amp;nbsp;for managment." style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="qup03jMZmrsR1gBGYmkV-6">
<mxGeometry x="120" y="370" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-14" value="Initialize MAVSDK and activate its listening connection port." style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="330" y="250" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-31" value="" style="endArrow=classic;html=1;rounded=0;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=-0.001;entryY=0.023;entryDx=0;entryDy=0;entryPerimeter=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="qup03jMZmrsR1gBGYmkV-14" target="qup03jMZmrsR1gBGYmkV-6">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="520" y="380" as="sourcePoint" />
<mxPoint x="470" y="280" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-66" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="qup03jMZmrsR1gBGYmkV-32" target="qup03jMZmrsR1gBGYmkV-34">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-32" value="Establish MySQL connection." style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="330" y="350" width="120" height="50" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-33" value="" style="endArrow=classic;html=1;rounded=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" target="qup03jMZmrsR1gBGYmkV-32">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="487" y="330" as="sourcePoint" />
<mxPoint x="570" y="420" as="targetPoint" />
<Array as="points">
<mxPoint x="390" y="330" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-122" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="qup03jMZmrsR1gBGYmkV-34" target="qup03jMZmrsR1gBGYmkV-41">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="300" y="470" />
<mxPoint x="300" y="80" />
<mxPoint x="210" y="80" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-124" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="qup03jMZmrsR1gBGYmkV-34" target="qup03jMZmrsR1gBGYmkV-123">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-34" value="is &lt;br&gt;terminated&lt;br&gt;be SET" style="rhombus;whiteSpace=wrap;html=1;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="350" y="430" width="80" height="80" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-40" value="" style="endArrow=block;dashed=1;html=1;rounded=0;strokeWidth=1;endFill=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="qup03jMZmrsR1gBGYmkV-12">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="750" y="390" as="sourcePoint" />
<mxPoint x="800" y="340" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-115" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="qup03jMZmrsR1gBGYmkV-41" target="qup03jMZmrsR1gBGYmkV-114">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-41" value="foreach handlerInfo&amp;nbsp; object&amp;nbsp;in&amp;nbsp;&lt;br&gt;&lt;i style=&quot;border-color: var(--border-color);&quot;&gt;&lt;u style=&quot;border-color: var(--border-color);&quot;&gt;systemHandlerInfos.&lt;/u&gt;&lt;/i&gt;" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="150" y="100" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-131" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="qup03jMZmrsR1gBGYmkV-42" target="qup03jMZmrsR1gBGYmkV-130">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-42" value="State Machine (handlerInfo.handlerState&lt;span style=&quot;background-color: initial;&quot;&gt;)&lt;/span&gt;" style="swimlane;whiteSpace=wrap;html=1;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="-650" y="240" width="930" height="860" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-58" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="qup03jMZmrsR1gBGYmkV-42" source="qup03jMZmrsR1gBGYmkV-43" target="qup03jMZmrsR1gBGYmkV-51">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-63" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="qup03jMZmrsR1gBGYmkV-42" source="qup03jMZmrsR1gBGYmkV-43" target="qup03jMZmrsR1gBGYmkV-49">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-43" value="Case :&amp;nbsp;&lt;br&gt;&lt;font style=&quot;font-size: 12px;&quot;&gt;State &lt;/font&gt;is &lt;br&gt;Init." style="rhombus;whiteSpace=wrap;html=1;" vertex="1" parent="qup03jMZmrsR1gBGYmkV-42">
<mxGeometry x="720" y="40" width="80" height="70" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-99" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="qup03jMZmrsR1gBGYmkV-42" source="qup03jMZmrsR1gBGYmkV-49" target="qup03jMZmrsR1gBGYmkV-98">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-49" value="INSERT new row &lt;br&gt;to MySQL" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="qup03jMZmrsR1gBGYmkV-42">
<mxGeometry x="700" y="460" width="120" height="40" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-73" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=1;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="qup03jMZmrsR1gBGYmkV-42" source="qup03jMZmrsR1gBGYmkV-50" target="qup03jMZmrsR1gBGYmkV-72">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="760" y="825" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-50" value="Change state to&lt;br&gt;Prologue" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="qup03jMZmrsR1gBGYmkV-42">
<mxGeometry x="715" y="740" width="90" height="40" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-59" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="qup03jMZmrsR1gBGYmkV-42" source="qup03jMZmrsR1gBGYmkV-51" target="qup03jMZmrsR1gBGYmkV-54">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-51" value="Case :&amp;nbsp;&lt;br&gt;&lt;font style=&quot;font-size: 12px;&quot;&gt;State &lt;/font&gt;is &lt;br&gt;Prologue" style="rhombus;whiteSpace=wrap;html=1;" vertex="1" parent="qup03jMZmrsR1gBGYmkV-42">
<mxGeometry x="570" y="40" width="80" height="70" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-60" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="qup03jMZmrsR1gBGYmkV-42" source="qup03jMZmrsR1gBGYmkV-54" target="qup03jMZmrsR1gBGYmkV-55">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-67" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="qup03jMZmrsR1gBGYmkV-42" source="qup03jMZmrsR1gBGYmkV-54" target="qup03jMZmrsR1gBGYmkV-65">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-54" value="&lt;u&gt;mysqlSN&lt;/u&gt;&lt;br&gt;has &lt;br&gt;value?" style="rhombus;whiteSpace=wrap;html=1;" vertex="1" parent="qup03jMZmrsR1gBGYmkV-42">
<mxGeometry x="570" y="130" width="80" height="80" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-61" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="qup03jMZmrsR1gBGYmkV-42" source="qup03jMZmrsR1gBGYmkV-55" target="qup03jMZmrsR1gBGYmkV-56">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-76" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=1;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="qup03jMZmrsR1gBGYmkV-42" source="qup03jMZmrsR1gBGYmkV-55" target="qup03jMZmrsR1gBGYmkV-86">
<mxGeometry relative="1" as="geometry">
<mxPoint x="550" y="330" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-55" value="check connection&lt;br&gt;from&amp;nbsp;&lt;br&gt;&lt;i&gt;&lt;u&gt;gHandlerMask&lt;/u&gt;&lt;/i&gt;" style="rhombus;whiteSpace=wrap;html=1;" vertex="1" parent="qup03jMZmrsR1gBGYmkV-42">
<mxGeometry x="570" y="240" width="80" height="80" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-77" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=1;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="qup03jMZmrsR1gBGYmkV-42" source="qup03jMZmrsR1gBGYmkV-56" target="qup03jMZmrsR1gBGYmkV-72">
<mxGeometry relative="1" as="geometry">
<mxPoint x="500" y="390" as="targetPoint" />
<Array as="points">
<mxPoint x="430" y="390" />
<mxPoint x="430" y="825" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-56" value="&lt;u&gt;&lt;i&gt;gTelemetryInfo&lt;/i&gt;&lt;/u&gt;&lt;br&gt;has any data?" style="rhombus;whiteSpace=wrap;html=1;" vertex="1" parent="qup03jMZmrsR1gBGYmkV-42">
<mxGeometry x="570" y="350" width="80" height="80" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-74" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=1;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="qup03jMZmrsR1gBGYmkV-42" source="qup03jMZmrsR1gBGYmkV-57" target="qup03jMZmrsR1gBGYmkV-72">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="610" y="825" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-57" value="Change state to&lt;br&gt;Ready" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="qup03jMZmrsR1gBGYmkV-42">
<mxGeometry x="560" y="740" width="100" height="40" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-87" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=1;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="qup03jMZmrsR1gBGYmkV-42" source="qup03jMZmrsR1gBGYmkV-65" target="qup03jMZmrsR1gBGYmkV-72">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="430" y="170" />
<mxPoint x="430" y="825" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-65" value="Error Detect!&lt;br&gt;Set terminated" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="qup03jMZmrsR1gBGYmkV-42">
<mxGeometry x="450" y="150" width="90" height="40" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-69" value="Yes" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" vertex="1" parent="qup03jMZmrsR1gBGYmkV-42">
<mxGeometry x="610" y="210" width="40" height="30" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-70" value="Yes" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" vertex="1" parent="qup03jMZmrsR1gBGYmkV-42">
<mxGeometry x="610" y="320" width="40" height="30" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-71" value="Yes" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" vertex="1" parent="qup03jMZmrsR1gBGYmkV-42">
<mxGeometry x="610" y="430" width="40" height="30" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-68" value="No" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" vertex="1" parent="qup03jMZmrsR1gBGYmkV-42">
<mxGeometry x="540" y="140" width="40" height="30" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-72" value="Continue" style="whiteSpace=wrap;html=1;" vertex="1" parent="qup03jMZmrsR1gBGYmkV-42">
<mxGeometry x="40" y="810" width="100" height="30" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-78" value="No" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" vertex="1" parent="qup03jMZmrsR1gBGYmkV-42">
<mxGeometry x="540" y="250" width="40" height="30" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-79" value="No" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" vertex="1" parent="qup03jMZmrsR1gBGYmkV-42">
<mxGeometry x="540" y="360" width="40" height="30" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-94" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="qup03jMZmrsR1gBGYmkV-42" source="qup03jMZmrsR1gBGYmkV-80" target="qup03jMZmrsR1gBGYmkV-91">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-80" value="Case :&amp;nbsp;&lt;br&gt;&lt;font style=&quot;font-size: 12px;&quot;&gt;State &lt;/font&gt;is &lt;br&gt;Ready" style="rhombus;whiteSpace=wrap;html=1;" vertex="1" parent="qup03jMZmrsR1gBGYmkV-42">
<mxGeometry x="270" y="40" width="80" height="70" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-83" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="qup03jMZmrsR1gBGYmkV-42" source="qup03jMZmrsR1gBGYmkV-81" target="qup03jMZmrsR1gBGYmkV-57">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-81" value="UPDATE state in MySQL" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="qup03jMZmrsR1gBGYmkV-42">
<mxGeometry x="550" y="460" width="120" height="40" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-82" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=0;entryDx=0;entryDy=0;exitX=0.5;exitY=1;exitDx=0;exitDy=0;" edge="1" parent="qup03jMZmrsR1gBGYmkV-42" source="qup03jMZmrsR1gBGYmkV-56" target="qup03jMZmrsR1gBGYmkV-81">
<mxGeometry relative="1" as="geometry">
<mxPoint x="570" y="440" as="sourcePoint" />
<mxPoint x="620" y="360" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-105" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="qup03jMZmrsR1gBGYmkV-42" source="qup03jMZmrsR1gBGYmkV-84" target="qup03jMZmrsR1gBGYmkV-97">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-84" value="Parsing &lt;u&gt;&lt;i&gt;gTelemetryInfo&lt;/i&gt;&lt;/u&gt;&lt;br&gt;into MySQL syntax" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="qup03jMZmrsR1gBGYmkV-42">
<mxGeometry x="250" y="360" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-89" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=1;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="qup03jMZmrsR1gBGYmkV-42" source="qup03jMZmrsR1gBGYmkV-86" target="qup03jMZmrsR1gBGYmkV-72">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="430" y="280" />
<mxPoint x="430" y="825" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-86" value="Change state to&lt;br&gt;Disconnected" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="qup03jMZmrsR1gBGYmkV-42">
<mxGeometry x="450" y="260" width="90" height="40" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-95" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="qup03jMZmrsR1gBGYmkV-42" source="qup03jMZmrsR1gBGYmkV-91" target="qup03jMZmrsR1gBGYmkV-84">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-103" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=0.5;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="qup03jMZmrsR1gBGYmkV-42" source="qup03jMZmrsR1gBGYmkV-91" target="qup03jMZmrsR1gBGYmkV-93">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-91" value="check connection&lt;br&gt;from&amp;nbsp;&lt;br&gt;&lt;i&gt;&lt;u&gt;gHandlerMask&lt;/u&gt;&lt;/i&gt;" style="rhombus;whiteSpace=wrap;html=1;" vertex="1" parent="qup03jMZmrsR1gBGYmkV-42">
<mxGeometry x="270" y="240" width="80" height="80" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-92" value="No" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" vertex="1" parent="qup03jMZmrsR1gBGYmkV-42">
<mxGeometry x="240" y="250" width="40" height="30" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-111" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=1;entryY=0.5;entryDx=0;entryDy=0;exitX=0.5;exitY=1;exitDx=0;exitDy=0;" edge="1" parent="qup03jMZmrsR1gBGYmkV-42" source="qup03jMZmrsR1gBGYmkV-93" target="qup03jMZmrsR1gBGYmkV-72">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-93" value="Change state to&lt;br&gt;Disconnected" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="qup03jMZmrsR1gBGYmkV-42">
<mxGeometry x="160" y="740" width="90" height="40" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-109" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="qup03jMZmrsR1gBGYmkV-42" source="qup03jMZmrsR1gBGYmkV-96" target="qup03jMZmrsR1gBGYmkV-108">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-96" value="clean gTelemetryInfo" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="qup03jMZmrsR1gBGYmkV-42">
<mxGeometry x="250" y="520" width="120" height="40" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-106" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="qup03jMZmrsR1gBGYmkV-42" source="qup03jMZmrsR1gBGYmkV-97" target="qup03jMZmrsR1gBGYmkV-96">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-97" value="UPDATE data into&lt;br&gt;MySQL" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="qup03jMZmrsR1gBGYmkV-42">
<mxGeometry x="250" y="460" width="120" height="40" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-100" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="qup03jMZmrsR1gBGYmkV-42" source="qup03jMZmrsR1gBGYmkV-98" target="qup03jMZmrsR1gBGYmkV-50">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-98" value="Get mysqlSN&lt;br&gt;from MySQL" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="qup03jMZmrsR1gBGYmkV-42">
<mxGeometry x="700" y="570" width="120" height="40" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-104" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="qup03jMZmrsR1gBGYmkV-42" source="qup03jMZmrsR1gBGYmkV-101" target="qup03jMZmrsR1gBGYmkV-102">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-101" value="Case :&amp;nbsp;&lt;br&gt;&lt;font style=&quot;font-size: 12px;&quot;&gt;State &lt;/font&gt;is &lt;br&gt;Disconnected" style="rhombus;whiteSpace=wrap;html=1;" vertex="1" parent="qup03jMZmrsR1gBGYmkV-42">
<mxGeometry x="50" y="40" width="80" height="70" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-107" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="qup03jMZmrsR1gBGYmkV-42" source="qup03jMZmrsR1gBGYmkV-102" target="qup03jMZmrsR1gBGYmkV-72">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-102" value="UPDATE state in MySQL" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="qup03jMZmrsR1gBGYmkV-42">
<mxGeometry x="30" y="460" width="120" height="40" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-113" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="qup03jMZmrsR1gBGYmkV-42" source="qup03jMZmrsR1gBGYmkV-108" target="qup03jMZmrsR1gBGYmkV-110">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-108" value="Get &lt;br&gt;Vehicle command &lt;br&gt;from MySQL" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#BFFBFF;" vertex="1" parent="qup03jMZmrsR1gBGYmkV-42">
<mxGeometry x="250" y="580" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-112" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=1;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="qup03jMZmrsR1gBGYmkV-42" source="qup03jMZmrsR1gBGYmkV-110" target="qup03jMZmrsR1gBGYmkV-72">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="310" y="825" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-110" value="Parsing&lt;br&gt;Vehicle command&lt;br&gt;into&amp;nbsp;&lt;i&gt;&lt;u&gt;gVehicleCommand&lt;/u&gt;&lt;/i&gt;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#BFFBFF;" vertex="1" parent="qup03jMZmrsR1gBGYmkV-42">
<mxGeometry x="250" y="660" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-116" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=0;entryDx=0;entryDy=0;exitX=0;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="qup03jMZmrsR1gBGYmkV-114" target="qup03jMZmrsR1gBGYmkV-42">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-114" value="Operate the handlerInfo object" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="150" y="180" width="120" height="40" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-119" value="No" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="320" y="430" width="40" height="30" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-127" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="qup03jMZmrsR1gBGYmkV-123" target="qup03jMZmrsR1gBGYmkV-126">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-123" value="Close MySQL connection." style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="330" y="550" width="120" height="50" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-125" value="Yes" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="390" y="510" width="40" height="30" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-129" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="qup03jMZmrsR1gBGYmkV-126" target="qup03jMZmrsR1gBGYmkV-128">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-126" value="Join &amp;amp; Tell &lt;br&gt;all thread to cutoff" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="330" y="640" width="120" height="50" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-128" value="STOP" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFCCCC;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="350" y="750" width="80" height="30" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-133" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="qup03jMZmrsR1gBGYmkV-130" target="qup03jMZmrsR1gBGYmkV-132">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-130" value="foreach handlerInfo&amp;nbsp; object&amp;nbsp;in&amp;nbsp;&lt;br&gt;&lt;i style=&quot;border-color: var(--border-color);&quot;&gt;&lt;u style=&quot;border-color: var(--border-color);&quot;&gt;systemHandlerInfos.&lt;/u&gt;&lt;/i&gt;" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="150" y="1140" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-134" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=1;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="qup03jMZmrsR1gBGYmkV-132" target="qup03jMZmrsR1gBGYmkV-34">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="470" y="1260" />
<mxPoint x="470" y="470" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-132" value="Remove handlerInfo object if the state is disconnected." style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="150" y="1230" width="120" height="60" as="geometry" />
</mxCell>
</root>
</mxGraphModel>
</diagram>
</mxfile>
+578
View File
@@ -0,0 +1,578 @@
<mxfile host="Electron" modified="2024-03-19T15:39:55.572Z" agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/22.1.18 Chrome/120.0.6099.199 Electron/28.1.2 Safari/537.36" etag="dIUk3_SABq-_l_q8tnzb" version="22.1.18" type="device">
<diagram id="C5RBs43oDa-KdzZeNtuy" name="Page-1">
<mxGraphModel dx="1927" dy="902" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
<root>
<mxCell id="WIyWlLk6GJQsqaUBKTNV-0" />
<mxCell id="WIyWlLk6GJQsqaUBKTNV-1" parent="WIyWlLk6GJQsqaUBKTNV-0" />
<mxCell id="qup03jMZmrsR1gBGYmkV-3" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="qup03jMZmrsR1gBGYmkV-1" target="qup03jMZmrsR1gBGYmkV-2" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-1" value="mavone.cpp" style="ellipse;whiteSpace=wrap;html=1;fillColor=#FFCCCC;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1">
<mxGeometry x="350" y="10" width="80" height="40" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-5" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="qup03jMZmrsR1gBGYmkV-2" target="qup03jMZmrsR1gBGYmkV-4" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-2" value="Input config file name" style="rounded=1;whiteSpace=wrap;html=1;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1">
<mxGeometry x="330" y="80" width="120" height="40" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-29" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="qup03jMZmrsR1gBGYmkV-4" target="qup03jMZmrsR1gBGYmkV-14" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-4" value="Read config file content and parse into&amp;nbsp;&lt;i&gt;&lt;u&gt;initSetting&lt;/u&gt;&lt;/i&gt;&lt;span style=&quot;background-color: initial;&quot;&gt;&amp;nbsp;&lt;/span&gt;" style="rounded=1;whiteSpace=wrap;html=1;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1">
<mxGeometry x="330" y="160" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-6" value="subscribe event&lt;br&gt;new MAVSDK::System detect" style="swimlane;whiteSpace=wrap;html=1;startSize=30;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1">
<mxGeometry x="487" y="270" width="253" height="440" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-9" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="qup03jMZmrsR1gBGYmkV-6" source="qup03jMZmrsR1gBGYmkV-7" target="qup03jMZmrsR1gBGYmkV-8" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-7" value="Get all connect MAVSDK::System list" style="rounded=1;whiteSpace=wrap;html=1;" parent="qup03jMZmrsR1gBGYmkV-6" vertex="1">
<mxGeometry x="10" y="40" width="120" height="40" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-11" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="qup03jMZmrsR1gBGYmkV-6" source="qup03jMZmrsR1gBGYmkV-8" target="qup03jMZmrsR1gBGYmkV-10" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-8" value="Contrast the list with &lt;i&gt;&lt;u&gt;systemHandlerInfos &lt;/u&gt;&lt;/i&gt;and pinpoint an object in the list that has a sysid exclusive to it." style="rounded=1;whiteSpace=wrap;html=1;" parent="qup03jMZmrsR1gBGYmkV-6" vertex="1">
<mxGeometry x="10" y="105" width="120" height="75" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-35" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="qup03jMZmrsR1gBGYmkV-6" source="qup03jMZmrsR1gBGYmkV-10" target="qup03jMZmrsR1gBGYmkV-12" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-36" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="qup03jMZmrsR1gBGYmkV-6" source="qup03jMZmrsR1gBGYmkV-10" target="qup03jMZmrsR1gBGYmkV-18" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-10" value="&lt;font style=&quot;font-size: 11px;&quot;&gt;Has an &lt;br&gt;object been &lt;br&gt;discovered?&lt;/font&gt;" style="rhombus;whiteSpace=wrap;html=1;" parent="qup03jMZmrsR1gBGYmkV-6" vertex="1">
<mxGeometry x="35" y="208" width="70" height="66" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-37" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="qup03jMZmrsR1gBGYmkV-6" source="qup03jMZmrsR1gBGYmkV-12" target="qup03jMZmrsR1gBGYmkV-16" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-12" value="Start an &lt;u style=&quot;&quot;&gt;&lt;b&gt;systemHandler&lt;/b&gt;&lt;/u&gt;&lt;span style=&quot;background-color: initial;&quot;&gt;&amp;nbsp;&lt;br&gt;thread for this MAVSDK::System object.&lt;/span&gt;" style="rounded=1;whiteSpace=wrap;html=1;" parent="qup03jMZmrsR1gBGYmkV-6" vertex="1">
<mxGeometry x="130" y="204" width="100" height="74" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-46" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="qup03jMZmrsR1gBGYmkV-6" source="qup03jMZmrsR1gBGYmkV-16" target="qup03jMZmrsR1gBGYmkV-45" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-16" value="Record the required information into an&amp;nbsp;&lt;i&gt;&lt;u&gt;handlerInfo&lt;/u&gt;&lt;/i&gt; object." style="rounded=1;whiteSpace=wrap;html=1;" parent="qup03jMZmrsR1gBGYmkV-6" vertex="1">
<mxGeometry x="120" y="290" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-18" value="END" style="whiteSpace=wrap;html=1;" parent="qup03jMZmrsR1gBGYmkV-6" vertex="1">
<mxGeometry x="40" y="390" width="60" height="20" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-23" value="Yes" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="qup03jMZmrsR1gBGYmkV-6" vertex="1">
<mxGeometry x="90" y="210" width="40" height="30" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-24" value="No" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="qup03jMZmrsR1gBGYmkV-6" vertex="1">
<mxGeometry x="35" y="274" width="40" height="30" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-47" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="qup03jMZmrsR1gBGYmkV-6" source="qup03jMZmrsR1gBGYmkV-45" target="qup03jMZmrsR1gBGYmkV-18" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-45" value="Add this handlerInfo object in&amp;nbsp;&lt;br&gt;&lt;i style=&quot;border-color: var(--border-color);&quot;&gt;&lt;u style=&quot;border-color: var(--border-color);&quot;&gt;systemHandlerInfos&lt;/u&gt;&lt;/i&gt;&lt;br&gt;&amp;nbsp;for managment." style="rounded=1;whiteSpace=wrap;html=1;" parent="qup03jMZmrsR1gBGYmkV-6" vertex="1">
<mxGeometry x="120" y="370" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-14" value="Initialize MAVSDK and activate its listening connection port." style="rounded=1;whiteSpace=wrap;html=1;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1">
<mxGeometry x="330" y="250" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-31" value="" style="endArrow=classic;html=1;rounded=0;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=-0.001;entryY=0.023;entryDx=0;entryDy=0;entryPerimeter=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="qup03jMZmrsR1gBGYmkV-14" target="qup03jMZmrsR1gBGYmkV-6" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="520" y="380" as="sourcePoint" />
<mxPoint x="470" y="280" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-66" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="qup03jMZmrsR1gBGYmkV-32" target="qup03jMZmrsR1gBGYmkV-34" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-32" value="Establish MySQL connection." style="rounded=1;whiteSpace=wrap;html=1;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1">
<mxGeometry x="330" y="350" width="120" height="50" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-33" value="" style="endArrow=classic;html=1;rounded=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" target="qup03jMZmrsR1gBGYmkV-32" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="487" y="330" as="sourcePoint" />
<mxPoint x="570" y="420" as="targetPoint" />
<Array as="points">
<mxPoint x="390" y="330" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-122" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="qup03jMZmrsR1gBGYmkV-34" target="qup03jMZmrsR1gBGYmkV-41" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="300" y="470" />
<mxPoint x="300" y="80" />
<mxPoint x="210" y="80" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-124" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="qup03jMZmrsR1gBGYmkV-34" target="qup03jMZmrsR1gBGYmkV-123" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-34" value="is &lt;br&gt;terminated&lt;br&gt;be SET" style="rhombus;whiteSpace=wrap;html=1;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1">
<mxGeometry x="350" y="430" width="80" height="80" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-40" value="" style="endArrow=block;dashed=1;html=1;rounded=0;strokeWidth=1;endFill=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=-0.004;entryY=0.778;entryDx=0;entryDy=0;entryPerimeter=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="qup03jMZmrsR1gBGYmkV-12" target="qup03jMZmrsR1gBGYmkV-135" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="750" y="390" as="sourcePoint" />
<mxPoint x="800" y="340" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-115" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="qup03jMZmrsR1gBGYmkV-41" target="qup03jMZmrsR1gBGYmkV-114" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-41" value="foreach handlerInfo&amp;nbsp; object&amp;nbsp;in&amp;nbsp;&lt;br&gt;&lt;i style=&quot;border-color: var(--border-color);&quot;&gt;&lt;u style=&quot;border-color: var(--border-color);&quot;&gt;systemHandlerInfos.&lt;/u&gt;&lt;/i&gt;" style="rounded=1;whiteSpace=wrap;html=1;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1">
<mxGeometry x="150" y="100" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-131" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="qup03jMZmrsR1gBGYmkV-42" target="qup03jMZmrsR1gBGYmkV-130" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-42" value="State Machine (handlerInfo.handlerState&lt;span style=&quot;background-color: initial;&quot;&gt;)&lt;/span&gt;" style="swimlane;whiteSpace=wrap;html=1;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1">
<mxGeometry x="-650" y="240" width="930" height="860" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-58" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="qup03jMZmrsR1gBGYmkV-42" source="qup03jMZmrsR1gBGYmkV-43" target="qup03jMZmrsR1gBGYmkV-51" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-63" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="qup03jMZmrsR1gBGYmkV-42" source="qup03jMZmrsR1gBGYmkV-43" target="qup03jMZmrsR1gBGYmkV-49" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-43" value="Case :&amp;nbsp;&lt;br&gt;&lt;font style=&quot;font-size: 12px;&quot;&gt;State &lt;/font&gt;is &lt;br&gt;Init." style="rhombus;whiteSpace=wrap;html=1;" parent="qup03jMZmrsR1gBGYmkV-42" vertex="1">
<mxGeometry x="720" y="40" width="80" height="70" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-99" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="qup03jMZmrsR1gBGYmkV-42" source="qup03jMZmrsR1gBGYmkV-49" target="qup03jMZmrsR1gBGYmkV-98" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-49" value="INSERT new row &lt;br&gt;to MySQL" style="rounded=1;whiteSpace=wrap;html=1;" parent="qup03jMZmrsR1gBGYmkV-42" vertex="1">
<mxGeometry x="700" y="460" width="120" height="40" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-73" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=1;entryY=0.5;entryDx=0;entryDy=0;" parent="qup03jMZmrsR1gBGYmkV-42" source="qup03jMZmrsR1gBGYmkV-50" target="qup03jMZmrsR1gBGYmkV-72" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="760" y="825" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-50" value="Change state to&lt;br&gt;Prologue" style="rounded=1;whiteSpace=wrap;html=1;" parent="qup03jMZmrsR1gBGYmkV-42" vertex="1">
<mxGeometry x="715" y="740" width="90" height="40" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-59" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="qup03jMZmrsR1gBGYmkV-42" source="qup03jMZmrsR1gBGYmkV-51" target="qup03jMZmrsR1gBGYmkV-54" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-51" value="Case :&amp;nbsp;&lt;br&gt;&lt;font style=&quot;font-size: 12px;&quot;&gt;State &lt;/font&gt;is &lt;br&gt;Prologue" style="rhombus;whiteSpace=wrap;html=1;" parent="qup03jMZmrsR1gBGYmkV-42" vertex="1">
<mxGeometry x="570" y="40" width="80" height="70" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-60" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="qup03jMZmrsR1gBGYmkV-42" source="qup03jMZmrsR1gBGYmkV-54" target="qup03jMZmrsR1gBGYmkV-55" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-67" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="qup03jMZmrsR1gBGYmkV-42" source="qup03jMZmrsR1gBGYmkV-54" target="qup03jMZmrsR1gBGYmkV-65" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-54" value="&lt;u&gt;mysqlSN&lt;/u&gt;&lt;br&gt;has &lt;br&gt;value?" style="rhombus;whiteSpace=wrap;html=1;" parent="qup03jMZmrsR1gBGYmkV-42" vertex="1">
<mxGeometry x="570" y="130" width="80" height="80" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-61" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="qup03jMZmrsR1gBGYmkV-42" source="qup03jMZmrsR1gBGYmkV-55" target="qup03jMZmrsR1gBGYmkV-56" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-76" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=1;entryY=0.5;entryDx=0;entryDy=0;" parent="qup03jMZmrsR1gBGYmkV-42" source="qup03jMZmrsR1gBGYmkV-55" target="qup03jMZmrsR1gBGYmkV-86" edge="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="550" y="330" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-55" value="check connection&lt;br&gt;from&amp;nbsp;&lt;br&gt;&lt;i&gt;&lt;u&gt;gHandlerMask&lt;/u&gt;&lt;/i&gt;" style="rhombus;whiteSpace=wrap;html=1;" parent="qup03jMZmrsR1gBGYmkV-42" vertex="1">
<mxGeometry x="570" y="240" width="80" height="80" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-77" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=1;entryY=0.5;entryDx=0;entryDy=0;" parent="qup03jMZmrsR1gBGYmkV-42" source="qup03jMZmrsR1gBGYmkV-56" target="qup03jMZmrsR1gBGYmkV-72" edge="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="500" y="390" as="targetPoint" />
<Array as="points">
<mxPoint x="430" y="390" />
<mxPoint x="430" y="825" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-56" value="&lt;u&gt;&lt;i&gt;gTelemetryInfo&lt;/i&gt;&lt;/u&gt;&lt;br&gt;has any data?" style="rhombus;whiteSpace=wrap;html=1;" parent="qup03jMZmrsR1gBGYmkV-42" vertex="1">
<mxGeometry x="570" y="350" width="80" height="80" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-74" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=1;entryY=0.5;entryDx=0;entryDy=0;" parent="qup03jMZmrsR1gBGYmkV-42" source="qup03jMZmrsR1gBGYmkV-57" target="qup03jMZmrsR1gBGYmkV-72" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="610" y="825" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-57" value="Change state to&lt;br&gt;Ready" style="rounded=1;whiteSpace=wrap;html=1;" parent="qup03jMZmrsR1gBGYmkV-42" vertex="1">
<mxGeometry x="560" y="740" width="100" height="40" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-87" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=1;entryY=0.5;entryDx=0;entryDy=0;" parent="qup03jMZmrsR1gBGYmkV-42" source="qup03jMZmrsR1gBGYmkV-65" target="qup03jMZmrsR1gBGYmkV-72" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="430" y="170" />
<mxPoint x="430" y="825" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-65" value="Error Detect!&lt;br&gt;Set terminated" style="rounded=1;whiteSpace=wrap;html=1;" parent="qup03jMZmrsR1gBGYmkV-42" vertex="1">
<mxGeometry x="450" y="150" width="90" height="40" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-69" value="Yes" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="qup03jMZmrsR1gBGYmkV-42" vertex="1">
<mxGeometry x="610" y="210" width="40" height="30" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-70" value="Yes" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="qup03jMZmrsR1gBGYmkV-42" vertex="1">
<mxGeometry x="610" y="320" width="40" height="30" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-71" value="Yes" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="qup03jMZmrsR1gBGYmkV-42" vertex="1">
<mxGeometry x="610" y="430" width="40" height="30" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-68" value="No" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="qup03jMZmrsR1gBGYmkV-42" vertex="1">
<mxGeometry x="540" y="140" width="40" height="30" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-72" value="Continue" style="whiteSpace=wrap;html=1;" parent="qup03jMZmrsR1gBGYmkV-42" vertex="1">
<mxGeometry x="40" y="810" width="100" height="30" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-78" value="No" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="qup03jMZmrsR1gBGYmkV-42" vertex="1">
<mxGeometry x="540" y="250" width="40" height="30" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-79" value="No" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="qup03jMZmrsR1gBGYmkV-42" vertex="1">
<mxGeometry x="540" y="360" width="40" height="30" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-94" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" parent="qup03jMZmrsR1gBGYmkV-42" source="qup03jMZmrsR1gBGYmkV-80" target="qup03jMZmrsR1gBGYmkV-91" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-80" value="Case :&amp;nbsp;&lt;br&gt;&lt;font style=&quot;font-size: 12px;&quot;&gt;State &lt;/font&gt;is &lt;br&gt;Ready" style="rhombus;whiteSpace=wrap;html=1;" parent="qup03jMZmrsR1gBGYmkV-42" vertex="1">
<mxGeometry x="270" y="40" width="80" height="70" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-83" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="qup03jMZmrsR1gBGYmkV-42" source="qup03jMZmrsR1gBGYmkV-81" target="qup03jMZmrsR1gBGYmkV-57" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-81" value="UPDATE state in MySQL" style="rounded=1;whiteSpace=wrap;html=1;" parent="qup03jMZmrsR1gBGYmkV-42" vertex="1">
<mxGeometry x="550" y="460" width="120" height="40" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-82" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=0;entryDx=0;entryDy=0;exitX=0.5;exitY=1;exitDx=0;exitDy=0;" parent="qup03jMZmrsR1gBGYmkV-42" source="qup03jMZmrsR1gBGYmkV-56" target="qup03jMZmrsR1gBGYmkV-81" edge="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="570" y="440" as="sourcePoint" />
<mxPoint x="620" y="360" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-105" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="qup03jMZmrsR1gBGYmkV-42" source="qup03jMZmrsR1gBGYmkV-84" target="qup03jMZmrsR1gBGYmkV-97" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-84" value="Parsing &lt;u&gt;&lt;i&gt;gTelemetryInfo&lt;/i&gt;&lt;/u&gt;&lt;br&gt;into MySQL syntax" style="rounded=1;whiteSpace=wrap;html=1;" parent="qup03jMZmrsR1gBGYmkV-42" vertex="1">
<mxGeometry x="250" y="360" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-89" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=1;entryY=0.5;entryDx=0;entryDy=0;" parent="qup03jMZmrsR1gBGYmkV-42" source="qup03jMZmrsR1gBGYmkV-86" target="qup03jMZmrsR1gBGYmkV-72" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="430" y="280" />
<mxPoint x="430" y="825" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-86" value="Change state to&lt;br&gt;Disconnected" style="rounded=1;whiteSpace=wrap;html=1;" parent="qup03jMZmrsR1gBGYmkV-42" vertex="1">
<mxGeometry x="450" y="260" width="90" height="40" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-95" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="qup03jMZmrsR1gBGYmkV-42" source="qup03jMZmrsR1gBGYmkV-91" target="qup03jMZmrsR1gBGYmkV-84" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-103" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=0.5;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" parent="qup03jMZmrsR1gBGYmkV-42" source="qup03jMZmrsR1gBGYmkV-91" target="qup03jMZmrsR1gBGYmkV-93" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-91" value="check connection&lt;br&gt;from&amp;nbsp;&lt;br&gt;&lt;i&gt;&lt;u&gt;gHandlerMask&lt;/u&gt;&lt;/i&gt;" style="rhombus;whiteSpace=wrap;html=1;" parent="qup03jMZmrsR1gBGYmkV-42" vertex="1">
<mxGeometry x="270" y="240" width="80" height="80" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-92" value="No" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="qup03jMZmrsR1gBGYmkV-42" vertex="1">
<mxGeometry x="240" y="250" width="40" height="30" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-111" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=1;entryY=0.5;entryDx=0;entryDy=0;exitX=0.5;exitY=1;exitDx=0;exitDy=0;" parent="qup03jMZmrsR1gBGYmkV-42" source="qup03jMZmrsR1gBGYmkV-93" target="qup03jMZmrsR1gBGYmkV-72" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-93" value="Change state to&lt;br&gt;Disconnected" style="rounded=1;whiteSpace=wrap;html=1;" parent="qup03jMZmrsR1gBGYmkV-42" vertex="1">
<mxGeometry x="160" y="740" width="90" height="40" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-109" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="qup03jMZmrsR1gBGYmkV-42" source="qup03jMZmrsR1gBGYmkV-96" target="qup03jMZmrsR1gBGYmkV-108" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-96" value="clean gTelemetryInfo" style="rounded=1;whiteSpace=wrap;html=1;" parent="qup03jMZmrsR1gBGYmkV-42" vertex="1">
<mxGeometry x="250" y="520" width="120" height="40" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-106" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="qup03jMZmrsR1gBGYmkV-42" source="qup03jMZmrsR1gBGYmkV-97" target="qup03jMZmrsR1gBGYmkV-96" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-97" value="UPDATE data into&lt;br&gt;MySQL" style="rounded=1;whiteSpace=wrap;html=1;" parent="qup03jMZmrsR1gBGYmkV-42" vertex="1">
<mxGeometry x="250" y="460" width="120" height="40" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-100" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" parent="qup03jMZmrsR1gBGYmkV-42" source="qup03jMZmrsR1gBGYmkV-98" target="qup03jMZmrsR1gBGYmkV-50" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-98" value="Get mysqlSN&lt;br&gt;from MySQL" style="rounded=1;whiteSpace=wrap;html=1;" parent="qup03jMZmrsR1gBGYmkV-42" vertex="1">
<mxGeometry x="700" y="570" width="120" height="40" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-104" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="qup03jMZmrsR1gBGYmkV-42" source="qup03jMZmrsR1gBGYmkV-101" target="qup03jMZmrsR1gBGYmkV-102" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-101" value="Case :&amp;nbsp;&lt;br&gt;&lt;font style=&quot;font-size: 12px;&quot;&gt;State &lt;/font&gt;is &lt;br&gt;Disconnected" style="rhombus;whiteSpace=wrap;html=1;" parent="qup03jMZmrsR1gBGYmkV-42" vertex="1">
<mxGeometry x="50" y="40" width="80" height="70" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-107" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" parent="qup03jMZmrsR1gBGYmkV-42" source="qup03jMZmrsR1gBGYmkV-102" target="qup03jMZmrsR1gBGYmkV-72" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-102" value="UPDATE state in MySQL" style="rounded=1;whiteSpace=wrap;html=1;" parent="qup03jMZmrsR1gBGYmkV-42" vertex="1">
<mxGeometry x="30" y="460" width="120" height="40" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-113" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="qup03jMZmrsR1gBGYmkV-42" source="qup03jMZmrsR1gBGYmkV-108" target="qup03jMZmrsR1gBGYmkV-110" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-108" value="Get &lt;br&gt;Vehicle command &lt;br&gt;from MySQL" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#BFFBFF;" parent="qup03jMZmrsR1gBGYmkV-42" vertex="1">
<mxGeometry x="250" y="580" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-112" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=1;entryY=0.5;entryDx=0;entryDy=0;" parent="qup03jMZmrsR1gBGYmkV-42" source="qup03jMZmrsR1gBGYmkV-110" target="qup03jMZmrsR1gBGYmkV-72" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="310" y="825" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-110" value="Parsing&lt;br&gt;Vehicle command&lt;br&gt;into&amp;nbsp;&lt;i&gt;&lt;u&gt;gVehicleCommand&lt;/u&gt;&lt;/i&gt;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#BFFBFF;" parent="qup03jMZmrsR1gBGYmkV-42" vertex="1">
<mxGeometry x="250" y="660" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-116" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=0;entryDx=0;entryDy=0;exitX=0;exitY=0.5;exitDx=0;exitDy=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="qup03jMZmrsR1gBGYmkV-114" target="qup03jMZmrsR1gBGYmkV-42" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-114" value="Operate the handlerInfo object" style="rounded=1;whiteSpace=wrap;html=1;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1">
<mxGeometry x="150" y="180" width="120" height="40" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-119" value="No" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1">
<mxGeometry x="320" y="430" width="40" height="30" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-127" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="qup03jMZmrsR1gBGYmkV-123" target="qup03jMZmrsR1gBGYmkV-126" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-123" value="Close MySQL connection." style="rounded=1;whiteSpace=wrap;html=1;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1">
<mxGeometry x="330" y="550" width="120" height="50" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-125" value="Yes" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1">
<mxGeometry x="390" y="510" width="40" height="30" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-129" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="qup03jMZmrsR1gBGYmkV-126" target="qup03jMZmrsR1gBGYmkV-128" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-126" value="Join &amp;amp; Tell &lt;br&gt;all thread to cutoff" style="rounded=1;whiteSpace=wrap;html=1;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1">
<mxGeometry x="330" y="640" width="120" height="50" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-128" value="STOP" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#FFCCCC;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1">
<mxGeometry x="350" y="750" width="80" height="30" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-133" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="qup03jMZmrsR1gBGYmkV-130" target="qup03jMZmrsR1gBGYmkV-132" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-130" value="foreach handlerInfo&amp;nbsp; object&amp;nbsp;in&amp;nbsp;&lt;br&gt;&lt;i style=&quot;border-color: var(--border-color);&quot;&gt;&lt;u style=&quot;border-color: var(--border-color);&quot;&gt;systemHandlerInfos.&lt;/u&gt;&lt;/i&gt;" style="rounded=1;whiteSpace=wrap;html=1;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1">
<mxGeometry x="150" y="1140" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-134" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=1;entryY=0.5;entryDx=0;entryDy=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="qup03jMZmrsR1gBGYmkV-132" target="qup03jMZmrsR1gBGYmkV-34" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="470" y="1260" />
<mxPoint x="470" y="470" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-132" value="Remove handlerInfo object if the state is disconnected." style="rounded=1;whiteSpace=wrap;html=1;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1">
<mxGeometry x="150" y="1230" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="jvLHa8hEhrjO4LWS7YWt-44" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="qup03jMZmrsR1gBGYmkV-135" target="jvLHa8hEhrjO4LWS7YWt-0" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="qup03jMZmrsR1gBGYmkV-135" value="systemHandler.cpp" style="ellipse;whiteSpace=wrap;html=1;fillColor=#FFCCCC;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1">
<mxGeometry x="1025" y="10" width="110" height="50" as="geometry" />
</mxCell>
<mxCell id="jvLHa8hEhrjO4LWS7YWt-8" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="jvLHa8hEhrjO4LWS7YWt-0" target="jvLHa8hEhrjO4LWS7YWt-5" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="jvLHa8hEhrjO4LWS7YWt-0" value="Init variables &amp;amp; &lt;br&gt;set parameter" style="rounded=1;whiteSpace=wrap;html=1;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1">
<mxGeometry x="1020" y="100" width="120" height="40" as="geometry" />
</mxCell>
<mxCell id="jvLHa8hEhrjO4LWS7YWt-1" value="handlerInfo" style="swimlane;fontStyle=0;childLayout=stackLayout;horizontal=1;startSize=30;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;whiteSpace=wrap;html=1;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1">
<mxGeometry x="600" y="70" width="140" height="120" as="geometry" />
</mxCell>
<mxCell id="jvLHa8hEhrjO4LWS7YWt-2" value="Item 1" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="jvLHa8hEhrjO4LWS7YWt-1" vertex="1">
<mxGeometry y="30" width="140" height="30" as="geometry" />
</mxCell>
<mxCell id="jvLHa8hEhrjO4LWS7YWt-3" value="Item 2" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="jvLHa8hEhrjO4LWS7YWt-1" vertex="1">
<mxGeometry y="60" width="140" height="30" as="geometry" />
</mxCell>
<mxCell id="jvLHa8hEhrjO4LWS7YWt-4" value="Item 3" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="jvLHa8hEhrjO4LWS7YWt-1" vertex="1">
<mxGeometry y="90" width="140" height="30" as="geometry" />
</mxCell>
<mxCell id="jvLHa8hEhrjO4LWS7YWt-9" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="jvLHa8hEhrjO4LWS7YWt-5" target="jvLHa8hEhrjO4LWS7YWt-7" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="jvLHa8hEhrjO4LWS7YWt-39" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=0.5;exitDx=0;exitDy=0;endArrow=none;endFill=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="jvLHa8hEhrjO4LWS7YWt-5" edge="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="1080" y="349.9999999999999" as="targetPoint" />
<Array as="points">
<mxPoint x="990" y="215" />
<mxPoint x="990" y="350" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="jvLHa8hEhrjO4LWS7YWt-5" value="does this system have autopilot?" style="rhombus;whiteSpace=wrap;html=1;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1">
<mxGeometry x="1037.5" y="170" width="85" height="90" as="geometry" />
</mxCell>
<mxCell id="jvLHa8hEhrjO4LWS7YWt-6" value="subscribe event&lt;br&gt;telemetry data recieved" style="swimlane;whiteSpace=wrap;html=1;startSize=35;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1">
<mxGeometry x="1190" y="290" width="500" height="365" as="geometry" />
</mxCell>
<mxCell id="jvLHa8hEhrjO4LWS7YWt-18" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="jvLHa8hEhrjO4LWS7YWt-6" source="jvLHa8hEhrjO4LWS7YWt-10" target="jvLHa8hEhrjO4LWS7YWt-12" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="jvLHa8hEhrjO4LWS7YWt-10" value="for&amp;nbsp;latitude,&amp;nbsp;longitude" style="rounded=1;whiteSpace=wrap;html=1;" parent="jvLHa8hEhrjO4LWS7YWt-6" vertex="1">
<mxGeometry x="21.25" y="115" width="137.5" height="45" as="geometry" />
</mxCell>
<mxCell id="jvLHa8hEhrjO4LWS7YWt-11" value="Read data &lt;br&gt;from buffer" style="rounded=1;whiteSpace=wrap;html=1;" parent="jvLHa8hEhrjO4LWS7YWt-6" vertex="1">
<mxGeometry x="195" y="50" width="110" height="40" as="geometry" />
</mxCell>
<mxCell id="jvLHa8hEhrjO4LWS7YWt-23" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" parent="jvLHa8hEhrjO4LWS7YWt-6" source="jvLHa8hEhrjO4LWS7YWt-12" target="jvLHa8hEhrjO4LWS7YWt-13" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="90" y="275" />
<mxPoint x="250" y="275" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="jvLHa8hEhrjO4LWS7YWt-12" value="Convert a DOUBLE into a string with precision to &lt;br&gt;8 decimal places." style="rounded=1;whiteSpace=wrap;html=1;" parent="jvLHa8hEhrjO4LWS7YWt-6" vertex="1">
<mxGeometry x="30" y="205" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="jvLHa8hEhrjO4LWS7YWt-13" value="Compose t&lt;i&gt;&lt;u&gt;elemetryInfo&lt;/u&gt;&lt;/i&gt;" style="rounded=1;whiteSpace=wrap;html=1;" parent="jvLHa8hEhrjO4LWS7YWt-6" vertex="1">
<mxGeometry x="195" y="295" width="110" height="40" as="geometry" />
</mxCell>
<mxCell id="jvLHa8hEhrjO4LWS7YWt-19" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="jvLHa8hEhrjO4LWS7YWt-6" source="jvLHa8hEhrjO4LWS7YWt-14" target="jvLHa8hEhrjO4LWS7YWt-15" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="jvLHa8hEhrjO4LWS7YWt-14" value="for&amp;nbsp;latitude,&amp;nbsp;longitude&lt;br&gt;heading,&amp;nbsp;velocity,&lt;br&gt;eulerAngle(pitch, yaw, roll)&lt;br&gt;battery remain percent" style="rounded=1;whiteSpace=wrap;html=1;" parent="jvLHa8hEhrjO4LWS7YWt-6" vertex="1">
<mxGeometry x="170" y="105" width="160" height="75" as="geometry" />
</mxCell>
<mxCell id="jvLHa8hEhrjO4LWS7YWt-22" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="jvLHa8hEhrjO4LWS7YWt-6" source="jvLHa8hEhrjO4LWS7YWt-15" target="jvLHa8hEhrjO4LWS7YWt-13" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="jvLHa8hEhrjO4LWS7YWt-15" value="Convert a FLOAT &lt;br&gt;into a string with precision to &lt;br&gt;4 decimal places." style="rounded=1;whiteSpace=wrap;html=1;" parent="jvLHa8hEhrjO4LWS7YWt-6" vertex="1">
<mxGeometry x="190" y="205" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="jvLHa8hEhrjO4LWS7YWt-20" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="jvLHa8hEhrjO4LWS7YWt-6" source="jvLHa8hEhrjO4LWS7YWt-16" target="jvLHa8hEhrjO4LWS7YWt-17" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="jvLHa8hEhrjO4LWS7YWt-16" value="for&amp;nbsp;armed, inair" style="rounded=1;whiteSpace=wrap;html=1;" parent="jvLHa8hEhrjO4LWS7YWt-6" vertex="1">
<mxGeometry x="350" y="120" width="137.5" height="45" as="geometry" />
</mxCell>
<mxCell id="jvLHa8hEhrjO4LWS7YWt-21" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" parent="jvLHa8hEhrjO4LWS7YWt-6" source="jvLHa8hEhrjO4LWS7YWt-17" target="jvLHa8hEhrjO4LWS7YWt-13" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="419" y="275" />
<mxPoint x="250" y="275" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="jvLHa8hEhrjO4LWS7YWt-17" value="Convert BOOL to &lt;br&gt;a &#39;0&#39; or &#39;1&#39; string." style="rounded=1;whiteSpace=wrap;html=1;" parent="jvLHa8hEhrjO4LWS7YWt-6" vertex="1">
<mxGeometry x="358.75" y="205" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="jvLHa8hEhrjO4LWS7YWt-37" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="jvLHa8hEhrjO4LWS7YWt-7" edge="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="1185" y="310" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="jvLHa8hEhrjO4LWS7YWt-7" value="Set telemetry data transmission rate" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#FFFFFF;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1">
<mxGeometry x="1020" y="290" width="120" height="40" as="geometry" />
</mxCell>
<mxCell id="jvLHa8hEhrjO4LWS7YWt-30" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=1;entryY=0.5;entryDx=0;entryDy=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="jvLHa8hEhrjO4LWS7YWt-24" target="jvLHa8hEhrjO4LWS7YWt-26" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="1160" y="610" />
<mxPoint x="1160" y="440" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="jvLHa8hEhrjO4LWS7YWt-47" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="jvLHa8hEhrjO4LWS7YWt-24" target="jvLHa8hEhrjO4LWS7YWt-42" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="jvLHa8hEhrjO4LWS7YWt-24" value="Does &lt;i&gt;&lt;u&gt;gTelemetryInfo&lt;/u&gt;&lt;/i&gt;&lt;br&gt;have any&lt;br&gt;content?" style="rhombus;whiteSpace=wrap;html=1;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1">
<mxGeometry x="1040" y="570" width="80" height="80" as="geometry" />
</mxCell>
<mxCell id="jvLHa8hEhrjO4LWS7YWt-28" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="jvLHa8hEhrjO4LWS7YWt-25" target="jvLHa8hEhrjO4LWS7YWt-24" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="jvLHa8hEhrjO4LWS7YWt-25" value="Sleep 1 sec" style="rounded=1;whiteSpace=wrap;html=1;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1">
<mxGeometry x="1040" y="510" width="80" height="30" as="geometry" />
</mxCell>
<mxCell id="jvLHa8hEhrjO4LWS7YWt-27" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="jvLHa8hEhrjO4LWS7YWt-26" target="jvLHa8hEhrjO4LWS7YWt-25" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="jvLHa8hEhrjO4LWS7YWt-26" value="Retry count&lt;br&gt;less than&lt;br&gt;10?" style="rhombus;whiteSpace=wrap;html=1;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1">
<mxGeometry x="1040" y="400" width="80" height="80" as="geometry" />
</mxCell>
<mxCell id="jvLHa8hEhrjO4LWS7YWt-31" value="Yes" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1">
<mxGeometry x="1040" y="470" width="40" height="30" as="geometry" />
</mxCell>
<mxCell id="jvLHa8hEhrjO4LWS7YWt-32" value="Yes" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1">
<mxGeometry x="1040" y="640" width="40" height="30" as="geometry" />
</mxCell>
<mxCell id="jvLHa8hEhrjO4LWS7YWt-33" value="Yes" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1">
<mxGeometry x="1037.5" y="250" width="40" height="30" as="geometry" />
</mxCell>
<mxCell id="jvLHa8hEhrjO4LWS7YWt-38" value="" style="endArrow=classic;html=1;rounded=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" target="jvLHa8hEhrjO4LWS7YWt-26" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="1190" y="350" as="sourcePoint" />
<mxPoint x="1000" y="350" as="targetPoint" />
<Array as="points">
<mxPoint x="1080" y="350" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="jvLHa8hEhrjO4LWS7YWt-40" value="No" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1">
<mxGeometry x="1000" y="185" width="40" height="30" as="geometry" />
</mxCell>
<mxCell id="jvLHa8hEhrjO4LWS7YWt-41" value="No" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1">
<mxGeometry x="1120" y="580" width="40" height="30" as="geometry" />
</mxCell>
<mxCell id="jvLHa8hEhrjO4LWS7YWt-46" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="jvLHa8hEhrjO4LWS7YWt-42" target="jvLHa8hEhrjO4LWS7YWt-45" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="jvLHa8hEhrjO4LWS7YWt-54" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="jvLHa8hEhrjO4LWS7YWt-42" target="jvLHa8hEhrjO4LWS7YWt-53" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="jvLHa8hEhrjO4LWS7YWt-42" value="is diccon-nect?&lt;br&gt;or cutoff ?" style="rhombus;whiteSpace=wrap;html=1;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1">
<mxGeometry x="1040" y="710" width="80" height="80" as="geometry" />
</mxCell>
<mxCell id="jvLHa8hEhrjO4LWS7YWt-49" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="jvLHa8hEhrjO4LWS7YWt-45" target="jvLHa8hEhrjO4LWS7YWt-48" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="jvLHa8hEhrjO4LWS7YWt-45" value="Put telemetry into&amp;nbsp;&lt;i style=&quot;border-color: var(--border-color);&quot;&gt;&lt;u style=&quot;border-color: var(--border-color);&quot;&gt;gTelemetryInfo&lt;/u&gt;&lt;/i&gt;" style="rounded=1;whiteSpace=wrap;html=1;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1">
<mxGeometry x="1190" y="720" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="jvLHa8hEhrjO4LWS7YWt-51" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="jvLHa8hEhrjO4LWS7YWt-48" target="jvLHa8hEhrjO4LWS7YWt-50" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="jvLHa8hEhrjO4LWS7YWt-48" value="check cutoff flag" style="rounded=1;whiteSpace=wrap;html=1;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1">
<mxGeometry x="1190" y="810" width="120" height="30" as="geometry" />
</mxCell>
<mxCell id="jvLHa8hEhrjO4LWS7YWt-52" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="jvLHa8hEhrjO4LWS7YWt-50" target="jvLHa8hEhrjO4LWS7YWt-42" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="1340" y="875" />
<mxPoint x="1340" y="690" />
<mxPoint x="1080" y="690" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="jvLHa8hEhrjO4LWS7YWt-50" value="sleep 100 ms" style="rounded=1;whiteSpace=wrap;html=1;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1">
<mxGeometry x="1190" y="860" width="120" height="30" as="geometry" />
</mxCell>
<mxCell id="jvLHa8hEhrjO4LWS7YWt-56" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="jvLHa8hEhrjO4LWS7YWt-53" target="jvLHa8hEhrjO4LWS7YWt-55" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="jvLHa8hEhrjO4LWS7YWt-53" value="set disconnect flag" style="rounded=1;whiteSpace=wrap;html=1;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1">
<mxGeometry x="1020" y="810" width="120" height="30" as="geometry" />
</mxCell>
<mxCell id="jvLHa8hEhrjO4LWS7YWt-55" value="END" style="rounded=0;whiteSpace=wrap;html=1;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1">
<mxGeometry x="1042.5" y="860" width="75" height="30" as="geometry" />
</mxCell>
</root>
</mxGraphModel>
</diagram>
</mxfile>
+9
View File
@@ -0,0 +1,9 @@
root --- RCrVpHd2
webInterface --- w23FgwXnQ5
mavoneServer --- T7DVVh2Sue
GUIDev --- pwnUxXCGE5
GUIDev2 --- c7gDdUddvB
+11
View File
@@ -0,0 +1,11 @@
MAVSDKListeningPort=udp://:14550
mysqlHost=140.120.108.238
mysqlPort=1880
mysqlUser=root
mysqlPW=RCrVpHd2
mysqlDatabase=Mav_one
C=3.14
EOC
EOC 就是結尾了 所以這邊可以打註解
+62
View File
@@ -0,0 +1,62 @@
-- MySQL dump 10.13 Distrib 8.0.36, for Linux (x86_64)
--
-- Host: 172.17.0.2 Database: Mav_one
-- ------------------------------------------------------
-- Server version 8.0.29
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!50503 SET NAMES utf8mb4 */;
/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
/*!40103 SET TIME_ZONE='+00:00' */;
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
--
-- Table structure for table `NodeRed_one`
--
DROP TABLE IF EXISTS `NodeRed_one`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!50503 SET character_set_client = utf8mb4 */;
CREATE TABLE `NodeRed_one` (
`SerialNo` int NOT NULL AUTO_INCREMENT,
`create_time` datetime DEFAULT CURRENT_TIMESTAMP,
`update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`mavsys_connect_status` varchar(40) DEFAULT NULL,
`system_id` int NOT NULL,
`vehicle_type` varchar(10) DEFAULT NULL,
`vehicle_mode` varchar(10) DEFAULT NULL,
`vehicle_lat` double DEFAULT NULL,
`vehicle_lon` double DEFAULT NULL,
`vehicle_head` float DEFAULT NULL,
`vehicle_bat_volt` float DEFAULT NULL,
`vehicle_bat_perc` float DEFAULT NULL,
`vehicle_speed` float DEFAULT NULL,
`drone_alt` float DEFAULT NULL,
`drone_air` tinyint DEFAULT NULL,
`drone_arm` tinyint DEFAULT NULL,
`drone_pitch` float DEFAULT NULL,
`drone_roll` float DEFAULT NULL,
`drone_yaw` float DEFAULT NULL,
`StatusText` varchar(45) DEFAULT NULL,
`command_type` varchar(10) DEFAULT NULL,
`command_para1` double DEFAULT NULL,
`command_para2` double DEFAULT NULL,
PRIMARY KEY (`SerialNo`)
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
-- Dump completed on 2024-02-02 15:33:46
File diff suppressed because one or more lines are too long
+18 -1
View File
@@ -5,15 +5,26 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
project(mavone)
include_directories(/usr/include/mysql-cppconn-8/jdbc) # for mysqlcppconn
link_directories(/usr/lib/x86_64-linux-gnu) # for mysqlcppconn
add_library(mavoneSys_lib
systemHandler.cpp
globals.cpp
)
add_executable(mavone
mavone.cpp
)
find_package(MAVSDK REQUIRED)
# find MAVSDK package and accept only when MAVSDK version > 1.4.10
find_package(MAVSDK 1.4.10 REQUIRED)
target_link_libraries(mavone
MAVSDK::mavsdk
pthread
mysqlcppconn # for mysqlcppconn
mavoneSys_lib # for the lib i created
)
if(NOT MSVC)
@@ -21,3 +32,9 @@ if(NOT MSVC)
else()
add_compile_options(mavone PRIVATE -WX -W2)
endif()
-8
View File
@@ -1,8 +0,0 @@
A=Hello World
B=42
C=3.14
connectPort=udp://:14550
EOC
EOC 就是結尾了 所以這邊可以打註解
目前只有 connectPort 有功能
+40
View File
@@ -0,0 +1,40 @@
#include "globals.h"
#include <array>
/*
用簡單粗暴的全域變數讓主迴圈跟副迴圈傳遞資料
另外加個 互斥鎖(Mutex) 避免存取衝突
gTelemetryInfo
這個變數是存放 副迴圈 到 主迴圈的資訊 (主要是要讓無人機的 telemetry 藉由主迴圈再寫進資料庫)
資料形式為 systemid[INT] : { 資訊名稱[String] : 資訊內容[String] }
例如
gTelemetryInfo = {
1 : { "vehicle_lat" : "24.16584990", "vehicle_lon" : "120.99977417", "vehicle_head" : "167.01" },
2 : { "vehicle_bat" : "0.97", "drone_air" : "1" }
}
則代表裡面存有 system id 1 的 經緯度與航向 而 system id 2 有電量與滯空狀態
gVehicleCommand
gHandlerMask
這個變數是讓 主迴圈 得知 副迴圈 的連線狀態
gHandlerMask[sysid]["is_connected"]
這個變數是讓 主迴圈 通知 副迴圈 切斷Loop
gHandlerMask[sysid]["cutoff"]
*/
std::map<int, std::map<std::string, std::string>> gTelemetryInfo;
std::map<int, std::map<int, std::array<double, 2>>> gVehicleCommand;
std::map<int, std::map<std::string, int>> gHandlerMask;
std::mutex gTeleMtx;
std::mutex gComMtx;
+15
View File
@@ -0,0 +1,15 @@
// globals.h
#ifndef GLOBALS_H
#define GLOBALS_H
#include <map>
#include <string>
#include <mutex>
extern std::map<int, std::map<std::string, std::string>> gTelemetryInfo;
extern std::map<int, std::map<int, std::array<double, 2>>> gVehicleCommand;
extern std::map<int, std::map<std::string, int>> gHandlerMask;
extern std::mutex gTeleMtx;
extern std::mutex gComMtx;
#endif
+270 -348
View File
@@ -1,45 +1,10 @@
//
// Simple example to demonstrate how takeoff and land using MAVSDK.
//
#include <chrono>
#include <cstdint>
#include <mavsdk/mavsdk.h>
#include <mavsdk/plugins/action/action.h>
#include <mavsdk/plugins/telemetry/telemetry.h>
#include <mavsdk/plugins/mavlink_passthrough/mavlink_passthrough.h>
#include <iostream>
#include <fstream>
#include <sstream>
#include <future>
#include <memory>
#include <thread>
#include <vector>
#include <map>
using namespace mavsdk;
using std::chrono::seconds;
using std::this_thread::sleep_for;
struct MavInitParameter {
std::string connectPort;
std::string connectPort2;
int B;
float C;
};
struct systemHandlerInfo {
int systemID;
std::thread systemThread;
};
#include "mavone.h"
#include "systemHandler.h"
// 我無法解決跨執行緒的 promise 變數生命週期問題
// 用最智障的全域變數 (砍掉 promise 結構簡單好多)
std::map<int,std::map<std::string,float>> gTelemetryInfo;
#include "globals.h"
int initializeParameters(const std::string& filePath, MavInitParameter& initSetting) {
std::ifstream configFile(filePath);
@@ -60,12 +25,18 @@ int initializeParameters(const std::string& filePath, MavInitParameter& initSett
std::string value = line.substr(delimiterPos + 1);
// Check if the key matches any field in MavInitParameter
if (key == "connectPort") {
if (key == "MAVSDKListeningPort") {
initSetting.connectPort = value;
} else if (key == "connectPort2") {
initSetting.connectPort2 = value;
} else if (key == "B") {
initSetting.B = std::stoi(value);
} else if (key == "mysqlHost") {
initSetting.mysqlHost = value;
} else if (key == "mysqlPort") {
initSetting.mysqlPort = value;
} else if (key == "mysqlUser") {
initSetting.mysqlUser = value;
} else if (key == "mysqlPW") {
initSetting.mysqlPW = value;
} else if (key == "mysqlDatabase") {
initSetting.mysqlDatabase = value;
} else if (key == "C") {
initSetting.C = std::stof(value);
}
@@ -73,107 +44,87 @@ int initializeParameters(const std::string& filePath, MavInitParameter& initSett
parameters.push_back(line); // Add the parameter to the vector
}
configFile.close();
std::cout << "Parameters read successfully!" << std::endl;
std::cout << "(mavone.cpp:initializeParameters) Parameters read successfully!" << std::endl;
// Print all the parameters
for (const auto& parameter : parameters) {
std::cout << "Line: " << parameter << std::endl;
std::cout << "(mavone.cpp:initializeParameters) Line: " << parameter << std::endl;
}
return 0;
}
/*
* Important multi-threaded functions,
* handling system initialization, receiving messages and sending messages.
*/
void systemHandler(System& system) {
// Initialization
auto telemetry = Telemetry{system};
auto action = Action{system};
std::cout << "System " << static_cast<int>(system.get_system_id()) << " get in Thread. (debug)" << std::endl; // debug
// 這裡會對 mysql 上的指令 做第一次轉換,再放給 systemHandler 做第二次轉換
std::map<std::string, int> commandTypeMap = {
{"aGuided", 101},
{"aLand", 102},
{"aArm", 103},
{"aSetHeight", 104},
{"aTakeoff", 105},
{"aGoto", 106},
};
// Store telemetry information
std::map<std::string,float> telemetryInfo;
std::map<int, std::array<double, 2>> decodeMysqlCommand(std::string commandType, std::string Para1, std::string Para2) {
// std::cout << commandType << ", " << Para1 << ", " << Para2 <<std::endl; // for Dev
std::map<std::string, std::function<void()>> commandMapFunc;
std::map<int, std::array<double, 2>> result;
// Put all the subscriber init in this section
telemetry.subscribe_position([&system, &telemetryInfo](Telemetry::Position position) {
std::cout << "System ID: " << static_cast<int>(system.get_system_id()) << " Altitude: " << position.relative_altitude_m << " m\n"; // debug
switch (commandTypeMap[commandType]) {
case 0:
result[-1] = {0,0};
break;
case 101: // aGuided
result[1] = {4,0}; // means change mode to 4
break;
case 102: // aLand
result[1] = {9,0}; // means change mode to 9
break;
case 103: // aArm
result[11] = {0,0}; // means action arm
break;
case 104: // aSetHeight
try { result[13] = {std::stof(Para1),0}; } // means change height to Para1
catch (std::invalid_argument &e) {
result[-2] = {0,0};
}
break;
case 105: // aTakeoff
result[12] = {0,0}; // means action takeoff
break;
case 106: // aGoto
try { result[21] = {std::stof(Para1),std::stof(Para2)}; } // means goto
catch (std::invalid_argument &e) {
result[-2] = {0,0};
}
break;
}
// Store telemetry information
telemetryInfo["altitude"] = position.relative_altitude_m;
gTelemetryInfo[static_cast<int>(system.get_system_id())] = telemetryInfo;
});
// Loop
// Destroy
sleep_for(seconds(5));
// Thread Terminate
std::cout << "Thread Out " << static_cast<int>(system.get_system_id()) << std::endl;
return result;
}
// class systemHandler {
// private:
// Telemetry telemetry;
// Action action;
// public:
// std::map<std::string,float> telemetryInfo;
// std::map<std::string,float> actionCommand;
// // Constructor
// systemHandler(System& system) {
// // Initialization
// telemetry = Telemetry{system};
// action = Action{system};
// std::cout << "System " << static_cast<int>(system.get_system_id()) << " captured. (debug)" << std::endl; // debug
// telemetry.subscribe_position([&system, &telemetryInfo](Telemetry::Position position) {
// std::cout << "System ID: " << static_cast<int>(system.get_system_id()) << " Altitude: " << position.relative_altitude_m << " m\n"; // debug
// // Store telemetry information
// telemetryInfo["altitude"] = position.relative_altitude_m;
// });
// }
// // Loop
// void operator()() {
// std::cout << "Thread is running" << std::endl;
// }
// }
int main(int argc, char** argv)
{
reset = false;
// if (argc != 2) {
// std::cout << "Config File Needed! ex. config.txt" << std::endl;
// return 1;
// }
if (argc != 2) {
std::cout << "(mavone.cpp:main) Config File Needed! ex. config.txt " << std::endl;
return 1;
}
// Program Initial Read Setting from config file
struct MavInitParameter initSetting;
// auto i = initializeParameters(argv[1], initSetting);
auto i = initializeParameters("config.txt", initSetting);
auto i = initializeParameters(argv[1], initSetting);
// auto i = initializeParameters("config.txt", initSetting);
if (i == 1){
std::cerr << "Failed to open config file: " << argv[1] << std::endl;
std::cerr << "(mavone.cpp:main) Failed to open config file: " << argv[1] << std::endl;
}
// Start MAVSDK Server and connect to it.
Mavsdk mavsdk;
// Set this MAVLINK service has system id 197, component id 254, NOT send heartbeat
mavsdk::Mavsdk::Configuration mavserver_configuration(197,254,false);
mavsdk.set_configuration(mavserver_configuration);
ConnectionResult connection_result = mavsdk.add_any_connection(initSetting.connectPort);
if (connection_result != ConnectionResult::Success) {
std::cerr << "Connection failed: " << connection_result << '\n';
std::cerr << "(mavone.cpp:main) Connection failed: " << connection_result << '\n';
return 1;
}
@@ -184,256 +135,227 @@ int main(int argc, char** argv)
mavsdk.subscribe_on_new_system([&mavsdk, &systemHandlerInfos]() {
// Get the last subscribed system
auto comingSystems = mavsdk.systems();
std::shared_ptr<System> sys = comingSystems.back();
// Avoid Duplicate System ID (Component ID is careless, maybe determind by UUID will be better?)
for(int i = 0;i < systemHandlerInfos.size();i++) {
if(sys->get_system_id() == systemHandlerInfos[i].systemID){
comingSystems.pop_back();
if(comingSystems.size() != 0){
sys = comingSystems.back();
} else {
std::cout << "Duplicate System ID Collision : " << static_cast<int>(sys->get_system_id()) << std::endl;
return;
std::shared_ptr<System> sys;
int sysid;
// Avoid Duplicate System ID
bool duplicated;
// for(int i=0; i<comingSystems.size(); i++){
for(int i=comingSystems.size()-1; i>=0; i--){
sys = comingSystems[i];
if (!sys->is_connected()) {continue;}
sysid = static_cast<int>(sys->get_system_id());
duplicated = false;
for(int j=0; j<systemHandlerInfos.size(); j++){
if(sysid == systemHandlerInfos[j].systemID){
duplicated = true;
break; // this will break the j for loop
}
}
if(duplicated == false){
// Get New System
System& new_system = *sys; // make std::shared_ptr<MAVSDK::System> back to MAVSDK::System
std::cout << "(mavone.cpp:subscribe_on_new_system) system detect sysid : " << sysid << "(Debug)"<< std::endl; // debug
// Let handler progrem deal with System
std::thread systemHandleThread([&new_system]() {systemHandler(new_system);});
// gHandlerMask[sysid]["is_connected"] = 1;
systemHandlerInfos.push_back(systemHandlerInfo{
sysid,
std::move(systemHandleThread),
systemHandlerState::Init,
-1
});
// only get ONE system each time
break; // this will break the i for loop
}
}
// make std::shared_ptr<MAVSDK::System> back to MAVSDK::System
System& new_system = *sys;
std::cout << "system detect : " << static_cast<int>(new_system.get_system_id()) << "(Debug)"<< std::endl; // debug
// Let handler progrem deal with System
std::thread systemHandleThread([&new_system]() {systemHandler(new_system);});
systemHandlerInfos.push_back(systemHandlerInfo{
static_cast<int>(new_system.get_system_id()),
std::move(systemHandleThread),
});
});
// MySQL connection is here
sql::mysql::MySQL_Driver *driver;
sql::Connection *con;
sql::Statement *stmt;
sql::ResultSet *res;
try {
driver = sql::mysql::get_mysql_driver_instance();
con = driver->connect("tcp://" + initSetting.mysqlHost + ":" + initSetting.mysqlPort, initSetting.mysqlUser, initSetting.mysqlPW);
con->setSchema(initSetting.mysqlDatabase);
stmt = con->createStatement();
} catch (sql::SQLException &e) {
std::cout << "(mavone.cpp:main) MySQL Connection Error: " << e.what() << std::endl;
return 1;
}
// Main Loop is here
// -- 將這個服務目前的狀態 更新到 mysql 中
// -- 從 systemHandlerInfos 中 輪巡所有 system 檢查並處理是否有需要丟到 mysql 的資料
// -- 從 mysql 抓到指令 丟到 systemHandlerInfo
int randomValue;
std::string sqlString;
std::map<std::string,std::string> aTelemetryInfo;
sleep_for(seconds(3));
while (!reset) {
std::cout << "mark A" << gTelemetryInfo[1]["altitude"] << std::endl;
sleep_for(seconds(1)); // debug
// 每個 System 輪詢過去
for ( auto& handlerInfo : systemHandlerInfos) {
switch (handlerInfo.handlerState) {
case systemHandlerState::Init :
std::cout << "(mavone.cpp:while) SystemHandler:" << std::to_string(handlerInfo.systemID) << " at Init " << std::endl; //debug
// 用系統時間生成的隨機數 標記目前欄位
std::srand(std::time(0));
randomValue = std::rand() % 10000;
sqlString = "INSERT INTO NodeRed_one (system_id, mavsys_connect_status) VALUES (" + std::to_string(handlerInfo.systemID) + ", " + std::to_string(randomValue) + ");";
// std::cout << "MySQL Insert Query: " << sqlString << std::endl; //debug
stmt->execute(sqlString);
// 取得對應的欄位序號 SerialNO
sqlString = "SELECT SerialNO FROM NodeRed_one WHERE system_id = " + std::to_string(handlerInfo.systemID) + " AND mavsys_connect_status = " +std::to_string(randomValue) + ";";
// std::cout << "MySQL SELECT Query: " << sqlString << std::endl; //debug
res = stmt->executeQuery(sqlString);
if (res->next()) {
// std::cout << "Query Reselt: " << res->getString(1) << std::endl; //debug
handlerInfo.mysqlSN = std::stof(res->getString(1));
}
// 切換到下一個狀態
handlerInfo.handlerState = systemHandlerState::Prologue;
// 更新 mavsys_connect_status 欄位
sqlString = "UPDATE NodeRed_one SET mavsys_connect_status = 'Prologue' WHERE SerialNO = " + std::to_string(handlerInfo.mysqlSN) + ";";
stmt->execute(sqlString);
break;
case systemHandlerState::Prologue :
std::cout << "(mavone.cpp:while) SystemHandler:" << std::to_string(handlerInfo.systemID) << " at Prologue " << std::endl; //debug
// 確認之前的 handlerInfo.mysqlSN 有正常被取得 若沒有整個程式即將關閉
if (handlerInfo.mysqlSN == -1) {
reset = true;
std::cout << "(mavone.cpp:while) handlerInfo.mysqlSN not aquired. Fatal Error. Shutdown all service. " << std::endl;
}
// 確認系統是否仍連線
if (gHandlerMask[handlerInfo.systemID]["is_connected"] == 0) {
handlerInfo.handlerState = systemHandlerState::Disconnected;
break;
}
// MAVSDK 還沒收到第一筆 telemetry 就持續在這個狀態
aTelemetryInfo = gTelemetryInfo[handlerInfo.systemID];
if (aTelemetryInfo.size() == 0) {
break;
}
// 切換到下一個狀態
handlerInfo.handlerState = systemHandlerState::Ready;
std::cout << "(mavone.cpp:while) SystemHandler:" << std::to_string(handlerInfo.systemID) << " into Ready " << std::endl; //debug
// 更新 mavsys_connect_status 欄位
sqlString = "UPDATE NodeRed_one SET mavsys_connect_status = 'Ready' WHERE SerialNO = " + std::to_string(handlerInfo.mysqlSN) + ";";
stmt->execute(sqlString);
case systemHandlerState::Ready :
// std::cout << "SystemHandler:" << std::to_string(handlerInfo.systemID) << " at Ready " << std::endl; //debug
// 確認系統是否仍連線
if (gHandlerMask[handlerInfo.systemID]["is_connected"] == 0) {
handlerInfo.handlerState = systemHandlerState::Disconnected;
break;
}
aTelemetryInfo = gTelemetryInfo[handlerInfo.systemID];
// TODO: 把 mysql 的指令放給 MAVSDK 準備傳到無人機
sqlString = "SELECT command_type,command_para1,command_para2 FROM NodeRed_one WHERE SerialNo = " \
+ std::to_string(handlerInfo.mysqlSN) + " AND command_type IS NOT NULL;";
res = stmt->executeQuery(sqlString);
if (res->next()) {
// 有讀到資料的話 就直接更新 gVehicleCommand
gComMtx.lock();
gVehicleCommand[handlerInfo.systemID] = decodeMysqlCommand(res->getString(1), res->getString(2), res->getString(3));
gComMtx.unlock();
// 本來想要把清空 mysql 的 command 欄位跟下面更新 telemetry 放一起 但是這樣會把程式複雜度弄上去 所以算了
sqlString = "UPDATE NodeRed_one SET command_type = NULL, command_para1 = NULL, command_para2 = NULL WHERE SerialNo = " \
+ std::to_string(handlerInfo.mysqlSN) + ";";
stmt->execute(sqlString);
}
// 把 MAVSDK 從無人機接到的 telemetry 放到 mysql
if(aTelemetryInfo.size() != 0) {
sqlString = "UPDATE NodeRed_one SET ";
for(const auto& pair : aTelemetryInfo) {
// std::cout << "Key: " << pair.first << ", Value: " << pair.second << std::endl; //debug
sqlString += pair.first + " = '" + pair.second + "',";
}
sqlString.pop_back();
sqlString += " WHERE SerialNO = " + std::to_string(handlerInfo.mysqlSN) + ";";
// std::cout << "MySQL UPDATE Query: " << sqlString << std::endl; //debug
stmt->execute(sqlString);
gTelemetryInfo[handlerInfo.systemID] = {};
}
// reset = true; //debug
break;
case systemHandlerState::Disconnected :
std::cout << "(mavone.cpp:while) SystemHandler:" << std::to_string(handlerInfo.systemID) << " at Disconnected. " << std::endl; //debug
// 更新 mavsys_connect_status 欄位
sqlString = "UPDATE NodeRed_one SET mavsys_connect_status = 'Disconnected' WHERE SerialNO = " + std::to_string(handlerInfo.mysqlSN) + ";";
stmt->execute(sqlString);
// 變更狀態
handlerInfo.handlerState = systemHandlerState::Terminate;
// reset = true; //debug
break;
}
}
// 刪除 Disconnected 的 handlerInfo
for (auto it = systemHandlerInfos.begin(); it != systemHandlerInfos.end(); /* no increment here */) {
if (it->handlerState == systemHandlerState::Terminate) {
// 這個 if 如果不加 則副程序在結束以前就會被主程序放生 執行時會出現 SIGABRT 錯誤
if (it->systemThread.joinable()) {
it->systemThread.join();
}
it = systemHandlerInfos.erase(it);
} else {
++it;
}
}
// make all thread join
for( auto& info : systemHandlerInfos){
info.systemThread.join();
}
// ==============================================================================
// When Progrem Terminate
reset = true;
// mavsdk.subscribe_on_new_system([&mavsdk]() {
// auto system = mavsdk.systems().back();
std::cout << "(mavone.cpp:main) Main Loop End !!!!!!" << std::endl;
// terminate MySQL Indicator
delete res;
delete stmt;
delete con;
// if (system->has_autopilot()) {
// std::cout << "Discovered autopilot\n";
// }
// });
// if (connection_result != ConnectionResult::Success) {
// std::cerr << "Connection failed: " << connection_result << '\n';
// return 1;
// }
// auto system = get_system(mavsdk);
// if (!system) {
// return 1;
// }
// for (auto system : mavsdk.systems()) {
// std::cout << "(mavsdk.systems) get id : " << static_cast<int>(system->get_system_id()) << std::endl;
// for (auto systemHandler : systemHandlers) {
// std::cout << systemHandler.systemID << " Mark B" << std::endl;
// if (systemHandler.systemID == static_cast<int>(system->get_system_id())) {
// std::cout << "Mark C" << std::endl;
// // telemetry = Telemetry{system};
// const auto set_rate_result = telemetry.set_rate_position(1);
// if (set_rate_result != Telemetry::Result::Success) {
// std::cerr << "Setting rate failed: " << set_rate_result << '\n';
// return 1;
// }
// telemetry.subscribe_position([systemHandler](Telemetry::Position position) {
// std::cout << "System ID: " << systemHandler.systemID << " Altitude: " << position.relative_altitude_m << " m\n";
// });
// // // Check until vehicle is ready to arm
// // while (telemetry.health_all_ok() != true) {
// // std::cout << "System ID: " << systemHandler.systemID << " Vehicle is getting ready to arm\n";
// // sleep_for(seconds(1));
// // }
// // // Arm vehicle
// // std::cout << "System ID: " << systemHandler.systemID << " Arming...\n";
// // const Action::Result arm_result = action.arm();
// // if (arm_result != Action::Result::Success) {
// // std::cerr << "System ID: " << systemHandler.systemID << " Arming failed: " << arm_result << '\n';
// // return 1;
// // }
// // telemetrys.push_back(telemetry);
// sleep_for(seconds(5));
// } else {
// std::cout << " Mark D " << std::endl;
// }
// }
// }
// std::cout << typeid().name() << std::endl;
// return 1;
// Instantiate plugins.
// auto telemetry = Telemetry{systemsList[0]};
// auto telemetry1 = Telemetry{systemsList[1]};
// // Instantiate plugins.
// auto telemetry = Telemetry{system};
// auto action = Action{system};
// // Instantiate mavlink_passthrough plugin.
// auto mavlink_passthrough = MavlinkPassthrough{system};
// auto x = static_cast<int>(system->get_system_id());
// std::cout << "System ID : " << x << '\n';
// System::AutopilotVersion y = system->get_autopilot_version_data();
// std::cout << "MAV_PROTOCOL_CAPABILITY : " << y.capabilities << '\n';
// std::cout << "Flight Stack Version : " << y.flight_sw_version << '\n';
// // Check vehicle mode
// const Telemetry::FlightMode mode_result = telemetry.flight_mode();
// std::cerr << "Vehicle Mode: " << mode_result << '\n';
// // return 1; // debug
// // Set the flight mode to "AUTO". use SET_MODE (#11) in MAVLink Messages.
// mavlink_message_t message;
// // mavlink_msg_set_mode_pack(mavlink_passthrough.get_our_sysid(),
// // mavlink_passthrough.get_our_compid(),
// // &message,
// // system->get_system_id(),
// // MAV_COMP_ID_AUTOPILOT1,
// // 4);
// mavlink_command_long_t command;
// command.target_system = system->get_system_id();
// command.target_component = MAV_COMP_ID_AUTOPILOT1;
// command.command = MAV_CMD_DO_SET_MODE;
// command.param1 = MAV_MODE_AUTO_ARMED;
// mavlink_msg_command_long_encode(mavlink_passthrough.get_our_sysid(),
// mavlink_passthrough.get_our_compid(),
// &message,
// &command);
// mavlink_passthrough.send_message(message);
// return 1; // debug
// We want to listen to the altitude of the drone at 1 Hz.
// const auto set_rate_result = telemetry0.set_rate_position(1);
// if (set_rate_result != Telemetry::Result::Success) {
// std::cerr << "Setting rate failed: " << set_rate_result << '\n';
// return 1;
// }
// const auto set_rate_result = telemetry1.set_rate_position(1);
// if (set_rate_result != Telemetry::Result::Success) {
// std::cerr << "Setting rate failed: " << set_rate_result << '\n';
// return 1;
// }
// Set up callback to monitor altitude while the vehicle is in flight
// auto x = systemsList[0]->get_system_id();
// telemetry.subscribe_position([x](Telemetry::Position position) {
// std::cout << "System ID: " << x << "Altitude: " << position.relative_altitude_m << " m\n";
// });
// std::cout << "Mark C" << std::endl;
// for(int i = 0; i < 5; ++i) {
// sleep_for(seconds(5));
// std::cout << "Number of discovered systems: " << systemsList.size() << std::endl;
// for (auto system : mavsdk.systems()) {
// std::cout << "Found system with system ID: " << static_cast<int>(system->get_system_id())
// << ", connected: " << (system->is_connected() ? "yes" : "no") << '\n';
// }
// std::cout << "link check " << i << " time. \n";
// }
// // Check until vehicle is ready to arm
// while (telemetry.health_all_ok() != true) {
// std::cout << "Vehicle is getting ready to arm\n";
// sleep_for(seconds(1));
// }
// // Arm vehicle
// std::cout << "Arming...\n";
// const Action::Result arm_result = action.arm();
// if (arm_result != Action::Result::Success) {
// std::cerr << "Arming failed: " << arm_result << '\n';
// return 1;
// }
// return 1; // debug
// // Take off
// std::cout << "Taking off...\n";
// const Action::Result takeoff_result = action.takeoff();
// if (takeoff_result != Action::Result::Success) {
// std::cerr << "Takeoff failed: " << takeoff_result << '\n';
// return 1;
// }
// Let it hover for a bit before landing again.
sleep_for(seconds(5));
// std::cout << "Landing...\n";
// const Action::Result land_result = action.land();
// if (land_result != Action::Result::Success) {
// std::cerr << "Land failed: " << land_result << '\n';
// return 1;
// }
// // Check if vehicle is still in air
// while (telemetry.in_air()) {
// std::cout << "Vehicle is landing...\n";
// sleep_for(seconds(1));
// }
// std::cout << "Landed!\n";
// // We are relying on auto-disarming but let's keep watching the telemetry for a bit longer.
// sleep_for(seconds(3));
// std::cout << "Finished...\n";
// make all thread join
for( auto& handlerInfo : systemHandlerInfos){
handlerInfo.systemThread.join();
}
return 0;
}
+67
View File
@@ -0,0 +1,67 @@
#ifndef MAVONE_H
#define MAVONE_H
#include <mavsdk/mavsdk.h>
#include <mavsdk/plugins/action/action.h>
#include <mavsdk/plugins/telemetry/telemetry.h>
#include <mavsdk/plugins/mavlink_passthrough/mavlink_passthrough.h>
#include <cstdint>
#include <iostream>
#include <fstream>
#include <sstream>
#include <iomanip>
#include <future>
#include <thread>
#include <chrono>
#include <vector>
#include <mutex>
#include <map>
#include <memory>
#include <mysql_driver.h>
#include <mysql_connection.h>
#include <cppconn/resultset.h>
#include <cppconn/statement.h>
using namespace mavsdk;
using std::chrono::seconds;
using std::chrono::milliseconds;
using std::this_thread::sleep_for;
struct MavInitParameter {
std::string connectPort;
std::string connectPort2;
float C;
std::string mysqlHost;
std::string mysqlPort;
std::string mysqlUser;
std::string mysqlPW;
std::string mysqlDatabase;
};
enum class systemHandlerState {
Init, // 剛剛交給 systemHandler 去處理
Prologue, // 建立了 mysql row 並取得 serialNo
Transmit, // 正在傳送指令到載具
Ready, // 收到第一筆並放到 telemetryInfo 後
Busy, // 載具正在執行上一次指令
Disconnected, // mavsdk 判斷該系統斷線了
Terminate, // 準備要從管理列表中刪除
// Void
};
struct systemHandlerInfo {
int systemID;
std::thread systemThread;
systemHandlerState handlerState;
int mysqlSN;
};
bool reset;
#endif
+492
View File
@@ -0,0 +1,492 @@
#include <mavsdk/mavsdk.h>
#include <mavsdk/plugins/info/info.h>
#include <mavsdk/plugins/param/param.h>
#include <mavsdk/plugins/action/action.h>
#include <mavsdk/plugins/telemetry/telemetry.h>
#include <mavsdk/plugins/mavlink_passthrough/mavlink_passthrough.h>
#include <cstdint>
#include <iostream>
#include <fstream>
#include <sstream>
#include <iomanip>
#include <future>
#include <thread>
#include <chrono>
#include <vector>
#include <mutex>
#include <map>
#include <memory>
#include "globals.h"
using namespace mavsdk;
using std::chrono::seconds;
using std::chrono::milliseconds;
using std::this_thread::sleep_for;
std::map<Telemetry::FlightMode, std::string> flightModeMap = {
{Telemetry::FlightMode::Unknown, "Unknown"},
{Telemetry::FlightMode::Takeoff, "Takeoff"},
{Telemetry::FlightMode::Ready, "Ready"},
{Telemetry::FlightMode::Hold, "Hold"},
{Telemetry::FlightMode::ReturnToLaunch, "Return To Launch"},
{Telemetry::FlightMode::Land, "Land"},
{Telemetry::FlightMode::Offboard, "Offboard"},
{Telemetry::FlightMode::FollowMe, "FollowMe"},
{Telemetry::FlightMode::Manual, "Manual"},
{Telemetry::FlightMode::Altctl, "Altctl"},
{Telemetry::FlightMode::Posctl, "Posctl"},
{Telemetry::FlightMode::Acro, "Acro"},
{Telemetry::FlightMode::Stabilized, "Stabilized"},
{Telemetry::FlightMode::Rattitude, "Rattitude"}
};
#define VEHICLE_CONTROL_ACTIVE
/*
* Important multi-threaded functions,
* handling system initialization, receiving messages and sending messages.
*/
void systemHandler(System& system) {
int sysid = static_cast<int>(system.get_system_id());
std::cout << "(systemHandler.cpp:systemHandler) System " << sysid << " get in Thread. (debug)" << std::endl; // debug
// Initialization
auto mavlink_passthrough = MavlinkPassthrough{system};
auto telemetry = Telemetry{system};
auto action = Action{system};
auto param = Param{system};
// Store telemetry information that will pass to main thread.
std::map<std::string,std::string> telemetryInfo;
// 控制指令 已經被主迴圈轉換過一次
std::map<int, std::array<double, 2>> vehicleCommand;
// 這些變數監控 handler 的行為
gHandlerMask[sysid]["cutoff"] = 0;
gHandlerMask[sysid]["is_connected"] = 1;
bool reset = false;
// 程序執行時會用到的變數
mavlink_message_t mav_message;
mavlink_command_int_t mav_command_int;
MavlinkPassthrough::CommandLong mav_command_long;
MavlinkPassthrough::Result result_mavpass;
Action::Result result_action;
int vehicle_type;
int _counter;
double _target_lon;
double _target_lat;
//
// std::cout << "Dev Test Start" << std::endl;
// // Get the info plugin for this drone
// auto atvData = system.get_autopilot_version_data();
// std::cout << "Autopilot Version Data:" << std::endl;
// std::cout << " Vendor ID: " << atvData.vendor_id << std::endl;
// std::cout << " Product ID: " << atvData.product_id << std::endl;
// std::cout << " Capabilities: " << atvData.capabilities << std::endl;
// std::cout << " Flight SW Version: " << atvData.flight_sw_version << std::endl;
// std::cout << " Middleware SW Version: " << atvData.middleware_sw_version << std::endl;
// std::cout << " OS SW Version: " << atvData.os_sw_version << std::endl;
// std::cout << " Board Version: " << atvData.board_version << std::endl;
// std::array<uint8_t, 18> uid = atvData.uid2;
// std::cout << "UID: ";
// for (const auto& byte : uid) {
// std::cout << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>(byte) << " ";
// }
// std::cout << std::endl;
// const Telemetry::FlightMode mode_result = telemetry.flight_mode();
// std::cerr << "Vehicle Mode: " << mode_result << '\n';
// sleep_for(milliseconds(500));
// // 演示一下 如何抓到 parameter
// auto get_result_i = param.get_param_int("VISO_TYPE"); // This function is blocking.
// std::cout << "Para Read: " << get_result_i.first << " : " << get_result_i.second << std::endl;
// std::pair<Param::Result, float> get_result_f = {Param::Result::Unknown , 0};
// get_result_f = param.get_param_float("RNGFND_FILT"); // This function is blocking.
// std::cout << "Para Read: " << get_result_f.first << " : " << get_result_f.second << std::endl;
// auto get_result = param.get_all_params(); // This function is blocking.
// auto int_p = get_result.int_params;
// for(const auto& item : int_p) {
// std::cout << item << std::endl;
// }
// // 抓一下 health
// auto health = telemetry.health();
// std::cout << "GYRO: " << (health.is_gyrometer_calibration_ok ? "OK" : "NG") << std::endl;
// std::cout << "Accelerometer: " << (health.is_accelerometer_calibration_ok ? "OK" : "NG") << std::endl;
// std::cout << "Magnetometer: " << (health.is_magnetometer_calibration_ok ? "OK" : "NG") << std::endl;
// std::cout << "Local position NED: " << (health.is_local_position_ok ? "OK" : "NG") << std::endl;
// std::cout << "Global position (Int): " << (health.is_global_position_ok ? "OK" : "NG") << std::endl;
// std::cout << "Home position: " << (health.is_home_position_ok ? "OK" : "NG") << std::endl;
// // 如果對接另一邊也是 mavsdk 這幾個 Parameter 要 provide,這邊讀看看
// get_result_i = {Param::Result::Unknown , 0};
// get_result_i = param.get_param_int("SYS_HITL"); // This function is blocking.
// std::cout << "Para Read: " << get_result_i.first << " : " << get_result_i.second << std::endl;
// get_result_i = {Param::Result::Unknown , 0};
// get_result_i = param.get_param_int("CAL_GYRO0_ID"); // This function is blocking.
// std::cout << "Para Read: " << get_result_i.first << " : " << get_result_i.second << std::endl;
// get_result_i = {Param::Result::Unknown , 0};
// get_result_i = param.get_param_int("CAL_ACC0_ID"); // This function is blocking.
// std::cout << "Para Read: " << get_result_i.first << " : " << get_result_i.second << std::endl;
// get_result_i = {Param::Result::Unknown , 0};
// get_result_i = param.get_param_int("CAL_MAG0_ID"); // This function is blocking.
// std::cout << "Para Read: " << get_result_i.first << " : " << get_result_i.second << std::endl;
// // 看看 has_autopilot() 的值
// std::cout << "Has AutoPilot : " << system.has_autopilot() << std::endl; // debug
// std::cout << "Dev Test End" << std::endl;
// Put all the subscriber init in this section
if (system.has_autopilot()) {
// 用 param 去判斷是什麼種類的 system
std::pair< Param::Result, int32_t > param_int_result;
vehicle_type = 0;
// 實體機驗證
// param_int_result = param.get_param_int("BATT_OPTIONS"); // 都有的
param_int_result = param.get_param_int("BRD_SBUS_OUT"); // 只有實體機
std::cout << "BRD_SBUS_OUT Para Read: " << param_int_result.first << " : " << param_int_result.second << std::endl; // debug
if (param_int_result.first == Param::Result::Success) { vehicle_type = 2; }
// 虛擬機驗證
param_int_result = param.get_param_int("INS_USE3"); // 只有虛擬機
std::cout << "INS_USE3 Para Read: " << param_int_result.first << " : " << param_int_result.second << std::endl; // debug
if (param_int_result.first == Param::Result::Success) { vehicle_type = 1; }
// =======================都用的==============================
auto set_rate_result = telemetry.set_rate_position(1.0);
// if (set_rate_result != mavsdk::Telemetry::Result::Success) {
// std::cout << "(systemHandler.cpp:systemHandler) Setting position rate failed:" << set_rate_result << std::endl;
// }
telemetry.subscribe_position([&system, &telemetryInfo](Telemetry::Position position) {
// 轉換數字到字串用的暫存變數
std::ostringstream num_str_ss;
// std::cout << "System ID: " << sysid << " Altitude: " << position.relative_altitude_m << " m\n"; // debug
// Store telemetry information
num_str_ss << std::fixed << std::setprecision(4) << position.relative_altitude_m;
telemetryInfo["drone_alt"] = num_str_ss.str();
num_str_ss.str("");
num_str_ss << std::fixed << std::setprecision(8) << position.latitude_deg;
telemetryInfo["vehicle_lat"] = num_str_ss.str();
num_str_ss.str("");
num_str_ss << std::fixed << std::setprecision(8) << position.longitude_deg;
telemetryInfo["vehicle_lon"] = num_str_ss.str();
num_str_ss.str("");
});
telemetry.subscribe_raw_gps([&system, &telemetryInfo](Telemetry::RawGps rawGps) {
// 轉換數字到字串用的暫存變數
std::ostringstream num_str_ss;
// Store telemetry information
num_str_ss << std::fixed << std::setprecision(4) << rawGps.velocity_m_s;
telemetryInfo["vehicle_speed"] = num_str_ss.str();
num_str_ss.str("");
});
telemetry.subscribe_heading([&system, &telemetryInfo](Telemetry::Heading heading) {
// 轉換數字到字串用的暫存變數
std::ostringstream num_str_ss;
// Store telemetry information
num_str_ss << std::fixed << std::setprecision(4) << heading.heading_deg;
telemetryInfo["vehicle_head"] = num_str_ss.str();
num_str_ss.str("");
});
if (vehicle_type == 2) {
set_rate_result = telemetry.set_rate_battery(1.0);
if (set_rate_result != mavsdk::Telemetry::Result::Success) {
std::cout << "(systemHandler.cpp:systemHandler) Setting battery rate failed:" << set_rate_result << std::endl;
}
}
telemetry.subscribe_battery([&system, &telemetryInfo](Telemetry::Battery battery) {
// 轉換數字到字串用的暫存變數
std::ostringstream num_str_ss;
// Store telemetry information
num_str_ss << std::fixed << std::setprecision(4) << battery.remaining_percent;
telemetryInfo["vehicle_bat_perc"] = num_str_ss.str();
num_str_ss.str("");
num_str_ss << std::fixed << std::setprecision(4) << battery.voltage_v;
telemetryInfo["vehicle_bat_volt"] = num_str_ss.str();
num_str_ss.str("");
});
telemetry.subscribe_armed([&system, &telemetryInfo](bool is_armed) {
if(is_armed){
telemetryInfo["drone_arm"] = "1";
}else{
telemetryInfo["drone_arm"] = "0";
}
});
// =======================只有無人機==============================
if (vehicle_type >= 1) {
// set_rate_result = telemetry.set_rate_attitude_euler(1.0); // only in v2.0
// if (set_rate_result != mavsdk::Telemetry::Result::Success) {
// std::cout << "(systemHandler.cpp:systemHandler) Setting euler rate failed:" << set_rate_result << std::endl;
// }
telemetry.subscribe_attitude_euler([&system, &telemetryInfo](Telemetry::EulerAngle eulerAngle) {
// 轉換數字到字串用的暫存變數
std::ostringstream num_str_ss;
// Store telemetry information
num_str_ss << std::fixed << std::setprecision(4) << eulerAngle.roll_deg;
telemetryInfo["drone_roll"] = num_str_ss.str();
num_str_ss.str("");
num_str_ss << std::fixed << std::setprecision(4) << eulerAngle.pitch_deg;
telemetryInfo["drone_pitch"] = num_str_ss.str();
num_str_ss.str("");
num_str_ss << std::fixed << std::setprecision(4) << eulerAngle.yaw_deg;
telemetryInfo["drone_yaw"] = num_str_ss.str();
num_str_ss.str("");
});
set_rate_result = telemetry.set_rate_in_air(1.0);
if (set_rate_result != mavsdk::Telemetry::Result::Success) {
std::cout << "(systemHandler.cpp:systemHandler) Setting in_air rate failed:" << set_rate_result << std::endl;
}
telemetry.subscribe_in_air([&system, &telemetryInfo](bool in_air) {
if(in_air){
telemetryInfo["drone_air"] = "1";
}else{
telemetryInfo["drone_air"] = "0";
}
});
telemetry.subscribe_flight_mode([&system, &telemetryInfo](Telemetry::FlightMode fightMode) {
telemetryInfo["vehicle_mode"] = flightModeMap[fightMode];
});
}
// =======================只有車子載具==============================
if (vehicle_type == 0) {
telemetry.subscribe_status_text([&system, &telemetryInfo]
(Telemetry::StatusText statusText) {
// 轉換數字到字串用的暫存變數
std::ostringstream num_str_ss;
std::istringstream _iss(statusText.text);
// 為了分析 statusText 字串的兩個暫存變數
std::string _token;
// std::cout << "(systemHandler.cpp:systemHandler) status_text: " << statusText.type << " ; " << statusText.text << std::endl; // debug
if(statusText.type == Telemetry::StatusTextType::Info) {
while (std::getline(_iss, _token, ',')) {
if (_token.at(0) == 'T') {
num_str_ss << std::fixed << std::setprecision(2) << std::stof(_token.substr(1));
telemetryInfo["vehicle_bat_Temp"] = num_str_ss.str();
num_str_ss.str("");
} else if (_token.at(0) == 'I') {
num_str_ss << std::fixed << std::setprecision(2) << std::stof(_token.substr(1));
telemetryInfo["vehicle_bat_current"] = num_str_ss.str();
num_str_ss.str("");
}
}
}
});
}
}
// std::string testA;
std::ostringstream testA;
// Wait Until telemetryInfo get something. and if nothing get from System for 10 sec will cut off this connection.
_counter = 0;
while(telemetryInfo.empty()){
sleep_for(seconds(1));
if(_counter++ > 10) {
reset = true;
std::cout << "(systemHandler.cpp:systemHandler) System " << sysid << " waiting too long without any coming info." << std::endl;
break;
}
}
switch (vehicle_type) {
case 2:
telemetryInfo["vehicle_type"] = "Real";
break;
case 1:
telemetryInfo["vehicle_type"] = "SITL";
break;
case 0:
telemetryInfo["vehicle_type"] = "Self";
break;
}
// Loop
while(system.is_connected() & !reset) {
// Send Telemetry Data
gTeleMtx.lock();
gTelemetryInfo[sysid] = telemetryInfo;
gTeleMtx.unlock();
// 取得來自主迴圈的指令 並清空
vehicleCommand = gVehicleCommand[sysid];
gComMtx.lock();
gVehicleCommand[sysid].clear();
gComMtx.unlock();
// Handler Command
reset = (gHandlerMask[sysid]["cutoff"] != 0);
// Vehicle Command
for ( auto& oneVehicleCommand : vehicleCommand ) {
if (vehicle_type == 0) { break; } // 不是飛機不吃指令
switch (oneVehicleCommand.first) {
case -1 :
std::cout << "(systemHandler.cpp:systemHandler) System " << sysid << " Get Error command_type! " << std::endl;
telemetryInfo["StatusText"] = "command_type Error!";
break;
case -2 :
std::cout << "(systemHandler.cpp:systemHandler) System " << sysid << " Get Error command_para! " << std::endl;
break;
// Here deal with the function of Change Mode
case 1 :
std::cout << "(systemHandler.cpp:systemHandler) System " << sysid << " Get Command Change Mode , " \
<< "Para1 : " << std::to_string(oneVehicleCommand.second[0]) \
<< ", Para2 : " << std::to_string(oneVehicleCommand.second[1]) << std::endl; // debug
#ifdef VEHICLE_CONTROL_ACTIVE
mav_command_long.target_sysid = sysid;
mav_command_long.target_compid = MAV_COMP_ID_AUTOPILOT1; // 這行指 component id = 1
mav_command_long.command = 176; // MAV_CMD_DO_SET_MODE
mav_command_long.param1 = 1; // 固定是 1
mav_command_long.param2 = static_cast<int>(oneVehicleCommand.second[0]); // mode
result_mavpass = mavlink_passthrough.send_command_long(mav_command_long); // 送出指令
// telemetryInfo["StatusText"] = result_mavpass;
std::cout << " ACK REL: " << result_mavpass << std::endl; // dev
// testA << result_mavpass;
#endif
break;
// Here deal with the function of Action Arm
case 11 :
std::cout << "(systemHandler.cpp:systemHandler) System " << sysid << " Get Command Arm, " \
<< "Para1 : " << std::to_string(oneVehicleCommand.second[0]) \
<< ", Para2 : " << std::to_string(oneVehicleCommand.second[1]) << std::endl; // debug
#ifdef VEHICLE_CONTROL_ACTIVE
result_action = action.arm();
// telemetryInfo["StatusText"] = result_mavpass;
std::cout << " ACK REL: " << result_action << std::endl; // dev
#endif
break;
// Here deal with the function of Action Takeoff
case 12 :
std::cout << "(systemHandler.cpp:systemHandler) System " << sysid << " Get Command Takeoff, " \
<< "Para1 : " << std::to_string(oneVehicleCommand.second[0]) \
<< ", Para2 : " << std::to_string(oneVehicleCommand.second[1]) << std::endl; // debug
#ifdef VEHICLE_CONTROL_ACTIVE
result_action = action.takeoff();
// telemetryInfo["StatusText"] = result_mavpass;
std::cout << " ACK REL: " << result_action << std::endl; // dev
_target_lat = std::stof(telemetryInfo["vehicle_lat"]);
_target_lon = std::stof(telemetryInfo["vehicle_lon"]);
#endif
break;
// Here deal with the function of change height
case 13 :
std::cout << "(systemHandler.cpp:systemHandler) System " << sysid << " Get Command Change Height, " \
<< "Para1 : " << std::to_string(oneVehicleCommand.second[0]) \
<< ", Para2 : " << std::to_string(oneVehicleCommand.second[1]) << std::endl; // debug
#ifdef VEHICLE_CONTROL_ACTIVE
// 若飛機滯空時 用 goto 方法到指定高度
// 若飛機在地時 用 set_takeoff_altitude 設定起飛高度
if (telemetryInfo["drone_air"] == "0") {
action.set_takeoff_altitude(static_cast<int>(oneVehicleCommand.second[0])); // mavsdk show error but still effect well (?)
} else {
mav_command_int.target_system = sysid; // Target system ID
mav_command_int.target_component = MAV_COMP_ID_AUTOPILOT1; // Target component ID
mav_command_int.command = MAV_CMD_DO_REPOSITION; // Command ID
mav_command_int.frame = MAV_FRAME_GLOBAL_RELATIVE_ALT; // Coordinate system
mav_command_int.x = _target_lat * 1E7; // Target latitude
mav_command_int.y = _target_lon * 1E7; // Target longitude
mav_command_int.z = static_cast<float>(oneVehicleCommand.second[0]); // Target altitude
mavlink_msg_command_int_encode(mavlink_passthrough.get_our_sysid(),
mavlink_passthrough.get_our_compid(),
&mav_message,
&mav_command_int);
// mavlink_passthrough.send_message(mav_message);
result_mavpass = mavlink_passthrough.send_message(mav_message);
std::cout << " ACK REL: " << result_mavpass << std::endl; // dev
std::cout << "x: " << std::to_string(_target_lon) << std::endl; // dev
std::cout << "y: " << std::to_string(_target_lat) << std::endl; // dev
}
#endif
break;
// Here deal with the function of GOTO
case 21 :
std::cout << "(systemHandler.cpp:systemHandler) System " << sysid << " Get Command GoTo, " \
<< "Para1 : " << std::to_string(oneVehicleCommand.second[0]) \
<< ", Para2 : " << std::to_string(oneVehicleCommand.second[1]) << std::endl; // debug
#ifdef VEHICLE_CONTROL_ACTIVE
mav_command_int.target_system = sysid; // Target system ID
mav_command_int.target_component = MAV_COMP_ID_AUTOPILOT1; // Target component ID
mav_command_int.command = MAV_CMD_DO_REPOSITION; // Command ID
mav_command_int.frame = MAV_FRAME_GLOBAL_RELATIVE_ALT; // Coordinate system
mav_command_int.x = oneVehicleCommand.second[0] * 1E7; // Target latitude
mav_command_int.y = oneVehicleCommand.second[1] * 1E7; // Target longitude
mav_command_int.z = std::stof(telemetryInfo["drone_alt"]); // Target altitude
mavlink_msg_command_int_encode(mavlink_passthrough.get_our_sysid(),
mavlink_passthrough.get_our_compid(),
&mav_message,
&mav_command_int);
result_mavpass = mavlink_passthrough.send_message(mav_message);
_target_lon = oneVehicleCommand.second[1];
_target_lat = oneVehicleCommand.second[0];
// telemetryInfo["StatusText"] = result_mavpass;
std::cout << " ACK REL: " << result_mavpass << std::endl; // dev
#endif
break;
}
}
// for purpose
sleep_for(milliseconds(100));
}
// Thread Terminate
std::cout << "(systemHandler.cpp:systemHandler) Thread Out " << sysid << std::endl; //debug
// Destroy
gHandlerMask[sysid]["is_connected"] = 0;
}
+7
View File
@@ -0,0 +1,7 @@
#ifndef SYSTEMHANDLER_H
#define SYSTEMHANDLER_H
void systemHandler(System& system);
#endif
@@ -0,0 +1,80 @@
#!/usr/bin/env python3
import asyncio
from mavsdk import System
from mavsdk.telemetry_server import (StatusText,StatusTextType,Battery,Position,VelocityNed, Heading,RawGps,GpsInfo,FixType)
import random
async def run():
# drone = System(port=50053, sysid=96, compid=1)
drone = System(port=50053)
print("456")
# await drone.connect(system_address="udp://127.0.0.1:14550")
await drone.connect()
print("123")
await drone.telemetry_server.publish_status_text(StatusText(StatusTextType.ALERT,"Check"))
# await drone.param_server.provide_param_int("CAL_ACC0_ID",1)
# await drone.param_server.provide_param_int("CAL_GYRO0_ID",1)
# await drone.param_server.provide_param_int("CAL_MAG0_ID",1)
# await drone.param_server.provide_param_int("SYS_HITL",0)
# await drone.param_server.provide_param_int("MIS_TAKEOFF_ALT",0)
a1 = drone.param_server.IntParam("CAL_ACC0_ID",1)
a2 = drone.param_server.IntParam("CAL_GYRO0_ID",1)
a3 = drone.param_server.IntParam("CAL_MAG0_ID",1)
a4 = drone.param_server.IntParam("SYS_HITL",0)
a5 = drone.param_server.IntParam("MIS_TAKEOFF_ALT",0)
while True:
remaining_percent = random.uniform(0.0, 1.0)
voltage_v = random.uniform(0.0, 20.0)
latitude_deg = random.uniform(0.0, 50.0)
longitude_deg = random.uniform(0.0, 180.0)
absolute_altitude_m = random.uniform(0.0, 50.0)
relative_altitude_m = random.uniform(0.0, 50.0)
heading_deg = random.uniform(0.0, 360.0)
position = Position(latitude_deg, longitude_deg,absolute_altitude_m,relative_altitude_m)
velocity_ned = VelocityNed(north_m_s=0.0, east_m_s=0.0, down_m_s=0.0)
heading = Heading(heading_deg)
raw_gps = RawGps(
timestamp_us=123456789, # 当前时间戳,以微秒为单位
latitude_deg=47.3977418, # 纬度
longitude_deg=8.5455934, # 经度
absolute_altitude_m=500, # 绝对海拔高度(米)
hdop=1.0, # 水平精度因子
vdop=1.0, # 垂直精度因子
velocity_m_s=random.uniform(0.0,50.0), # 速度(米/秒)
cog_deg=90.0, # 航向(度)
altitude_ellipsoid_m=510.0, # 大地水准面上的高度(米)
horizontal_uncertainty_m=1.000000000000, # 水平准确性(米)
vertical_uncertainty_m=1.00000000,
velocity_uncertainty_m_s=0.0000000000000000 ,# 垂直准确性(米)
heading_uncertainty_deg=1.0000000, # 速度准确性(米/秒)
yaw_deg=180.5# 是否已定位的标志
)
gps_info = GpsInfo(
num_satellites=10, # 卫星数量
fix_type=FixType.RTK_FIXED # GPS 修复类型
)
await drone.telemetry_server.publish_battery(Battery(voltage_v,remaining_percent))
await drone.telemetry_server.publish_position(position,velocity_ned,heading)
await drone.telemetry_server.publish_raw_gps(raw_gps,gps_info)
vehicle_battery_temperature = random.uniform(20.0,150.0) # 電池溫度
vehicle_battery_current = random.uniform(0.0,15.0) # 電池電流
vehicle_battery_CAT = "I" + str(vehicle_battery_current) + "," + "T" + str(vehicle_battery_temperature)
print(vehicle_battery_CAT)
await drone.telemetry_server.publish_status_text(StatusText(StatusTextType.INFO,vehicle_battery_CAT))
await asyncio.sleep(2)
#print("remaining_percent: ",remaining_percent)
if __name__ == "__main__":
loop = asyncio.get_event_loop()
loop.run_until_complete(run())