# DeviceTalk 資料庫說明 ## 總覽 ### api.models * Language * BasicFile * Library * DfType * LibraryFunction * SaFunction * DeviceLibrary * Device * DeviceHasLibrary * DeviceDf * DeviceLibraryDf * DeviceDfHasSaFunction * LibraryDfHasSaFunction ### file_handle.models * File * UploadBatch ## ERD ![](https://i.imgur.com/u7SKO36.png) ## 詳細說明 ### api.models.Language 記錄 DeviceTalk 中有哪些程式語言 * id: `<PK>` * name: `char(30)` name of the Language | id | name | | ----- | ------- | | 1 | Python | | 2 | C++ | ### api.models.BasicFile 繼承 `api.models.FileGroup` Basic file 是產生 SA code 的模板,在現在版本中,每種 Langugage 只會對應一個 BasicFile。考慮到未來擴充,將其對應關係定為一對多。 * id: `<PK>` * name: `char(100)` name of this basic file * dir_path: `char(255)` 此 basic file 在的 SA code 模板的根目錄路徑。一般訂為 * language: `<FK>`. Language ### api.models.Library 繼承 `api.models.FileGroup` Library 指的是由使用者上傳的。 * id: `<PK>` * name: `char(100)` name of this basic file * dir_path: `char(255)` 此 library 根目錄相對於 SA code 模板的根目錄相對路徑。 * basic_file: `<FK>` BasicFile * global_var_setup: `str` global variable 的內容 * gvs_readonly_lines: `JSON` global variable 中哪幾行是 readonly ### api.models.LibraryFunction 由使用者上傳的 Library 中的範例程式內容。顯示在 DeviceTalk GUI 的 DF Function Manager 左上列表中。 * id: `<PK>` * name: `char(100)` name of this library function * library: `FK` Library 接下來有數個 entry,皆為`str`,預設為`''`。表示 LibraryFunction 中有哪些 session。被定義在 `settings.LIBRARYFUNCTION_FIELDS` 中,預設為 `['var_define', 'import_string', 'init_content','runs_content']` ### api.models.DfType 定義 SaFunction, DeviceFeature 的 DF Type * id: `<PK>` * df_type: `union` (`idf`, `odf`) * params: `JSON` 各參數型態的 list | id | df_type | params | | ----- | ---- |----| | 1 | idf | ['int'] | | 2 | odf | ['float', 'float'] | ### api.models.SaFunction SAFunction 相較於 LibraryFunction,是由使用者在 DeviceTalk 上依照模板產生的 function。可以直接做為,DF在執行時呼叫的 function。 * id: `<PK>` * name: `char(100)` name of this sa function * var_setup: `JSON` 此 function variable setup 的預設值 * code: `JSON` 此 function 的內容 * readonly_lines: `JSON` code 中哪幾行是 readonly * updated_at: `datetime` 最後更新時間 * function_type: `FK` DfType * library_ref: `FK` LibraryFunction,可為 `None`。代表此 SaFunction 是依照哪個 LibraryFunction 產生的。 ### api.models.DeviceLibrary 繼承 `api.models.LibraryPoolBase` DeviceLibrary 相較於 Library,是由 DeviceTalk 產生的 library。 * id: `<PK>` * name: `char(100)` name of this device library * basic_file: `FK` DasicFile。代表此 DeviceLibrary 依據哪個 BasicFile 生成。 * user: `FK` User。代表由哪個 User 產生。 * global_var_setup: `str` global variable 的內容 * gvs_readonly_lines: `JSON` global variable 中哪幾行是 readonly * dir_path: `char(255)` 此 device library 根目錄相對於 SA code 模板的根目錄相對路徑。 * dependency_library `M2M` Library。這個 DeviceLibrary 使用哪些 Library。 * functions `M2M` SaFunction。這個 DeviceLibrary 中包含哪些 SaFunction。 ### api.models.Device 繼承 `api.models.LibraryPoolBase` 搭配 `api.models.DeviceHasLibrary`, `api.models.DeviceDf` 記錄 IoTalk device 的狀態。其他細節參考[Device 相關資訊儲存說明](#Device-相關資訊儲存說明) * id: `<PK>` * name: `char(100)` name of this device library * dm_name: `char(100)` name of device model * user: `FK` User。代表由哪個 User 產生。若為 `None` 代表此 device 是 global 的。所有使用者都看得到。 * basic_file: `FK` DasicFile。代表此 DeviceLibrary 依據哪個 BasicFile 生成。 * global_var_setup: `str` global variable 的內容 * gvs_readonly_lines: `JSON` global variable 中哪幾行是 readonly * functions `M2M` SaFunction。這個 Device 中包含哪些 SaFunction。 * server_url: `char(255)`。DeviceTalk GUI 中 DA Tab 的 IoTtalk Server 的內容。 * device_address: `char(50)`。DeviceTalk GUI 中 DA Tab 的 Device Address 的內容。 * push_interval: `float`。DeviceTalk GUI 中 DA Tab 的 Device Address 的內容。 ### api.models.DeviceHasLibrary 這個用來記錄各個 Device 有哪些 Library 的關係表。 * id: `<PK>` * device: `FK` Device * device_library: `FK` DeviceLibrary * library: `FK` Library * order: `int` 用來記錄使用者點及 library 的順序 ### api.models.DeviceDf 繼承 `DeviceFeatureBase` * id: `PK` * name: the name of this device feature * df_type: `FK` DfType * device: `FK` Device。說明這個 DF 屬於哪個 Device * functions: `M2M` SaFunction through DeviceDfHasSaFunction ### api.models.DeviceLibraryDf 繼承 `DeviceFeatureBase` * id: `PK` * name: the name of this device feature * df_type: `FK` DfType * device_library: `FK` DeviceLibrary。說明這個 DF 屬於哪個 DeviceLibrary * functions: `M2M` SaFunction through LibraryDeviceDfHasSaFunction 在 DeviceTalk 實作中,Device Feature 是各個 Device 分別記錄,也就是相同 DM 的兩個 Device,會有對應的兩組 DeviceDf。 ### api.models.DeviceDfHasSaFunction 繼承 `DfHasSaFunctionBase` * id: `PK` * function: `FK` SaFunction * device: `FK` Device * var_setup: `str` 此 DF 與 SaFunction 關係中的 variable setup 內容。 * selected: `boolean` 此 DF 是否選擇此 SaFunction。 ### api.models.DeviceDfHasSaFunction 繼承 `DfHasSaFunctionBase` * id: `PK` * function: `FK` SaFunction * device_library: `FK` DeviceLibrary * var_setup: `str` 此 DF 與 SaFunction 關係中的 variable setup 內容。 * selected: `boolean` 此 DF 是否選擇此 SaFunction。 DeviceFeature 中的 functions 紀錄此 DF 中包含哪些 SaFunction,但是在關係中,還有 `var_setup`, `selected` 兩個屬性,故自行實作 RelationTable ### file_handle.models.UploadBatch 單純紀錄每次上傳程序中,被上傳資料夾中的所有檔案物件 * id: `PK` ### file_handle.models.File * id: `PK` * file_path: `char(100)` * real_path: `char(200)` * is_upload: `boolean` 此檔案是否已上傳,若被建立超過一天仍為未上傳,在 scheduler 執行 cleanup 時會被清除。 * uuid: `UUID4` 此檔案的 uuid,必須是唯一的。 * created_at: `Datetime` 建立此 Entry 的時間 * updated_at: `Datetime` 最後更新此 Entry 的時間 * upload_batch: `FK` UploadBatch * library: `FK` Library * device_library: `FK` DeviceLibrary * basic_file: `FK` BasicFile * device: `one2one` Device DeviceTalk 的檔案管理實作中,藉由這個表格,讓所有有檔案的 table,在處理時,不用額外擔心實際的檔案純儲存在 server 的哪個路徑。 DeviceTalk 將所有檔案都放在 `<uploaddir>` 下,藉由將檔名透過 uuid 編碼,就可以不用擔心相同檔名衝突的問題。像是下表的`File:100`和`File:104`,檔名(file_path)都是`config.ini`,但屬於不同的 BasicFile。 | id | file_path | real_path | is_upload | uuid | library | basic_file | ... | | --- | ------ |--------------- | ------- | ----- | ----- | ----- | ----- | | 100 | config.ini | `<uploaddir>/abc1...` | T | abc1... | None | 1 | ... | | 101 | sa.py | `<uploaddir>/abc2...` | T | abc2... | None | 1 | ... | | 102 | Makefile | `<uploaddir>/abc3...` | T | abc3... | None | 1 | ... | | 103 | library/lib.py | `<uploaddir>/abc4...` | T | abc4... | None | 1 | ... | | 104 | config.ini | `<uploaddir>/abc5...` | T | abc5... | None | 2 | ... | | 105 | sa.cpp | `<uploaddir>/abc6...` | T | abc6... | None | 2 | ... | | 106 | Makefile | `<uploaddir>/abc7...` | T | abc7... | None | 2 | ... | 同時 file_handle.models.File 中提中 open 的 function,讓開發者可以直接以抽象的檔案架構中讀寫某檔案。 例如 `basicfile1_object.file_set.get(file_name='config.ini').open('r')` 意義等同 `open('<uploaddir>/abc1...', 'r')` ## Device 相關資訊儲存說明 ![](https://i.imgur.com/LuSRiyB.png) 上圖為與儲存 Device 資訊相關的 table ### Device 與 Library 的關係 在 DeviceTalk GUI 的 Library Selection 中顯示的 Library,在實作上,分成`Library`(table.d)及`DeviceLibrary`(table.c)來儲存,所以無法用單一的`M2M`關係來紀錄其關係。因此實作`DeviceHasLibrary`(table.f)來表示。 例如,下表代表`<Device:10>`依序選擇了`<Library:5>`, `<Library:3>`, `<DeviceLibrary:3>`,對應的`DeviceHasLibrary`中,會記錄的資料。 | id | device | device_library | library | order | | --- | ------ |--------------- | ------- | ----- | | 100 | 10 | null | 5 | 0 | | 101 | 10 | null | 3 | 1 | | 102 | 10 | 3 | null | 2 | 同一個 entry,`device_library`及`library`必需恰有一者為`None`,`order` 越大代表使用者越晚勾選的 library。 ### Device 與 Function 的關係 * 在 DeviceTalk GUI 的 DF Function Manager 中顯示的 Function。 * library function: 左上列表。對應 `LibraryFunction` (table.e) * SA function: 右上列表。對應 `SaFunction` (table.b) * 差異 * SA function 在一個 device 中,其內容是可以被使用者新增、修正、刪除的,因此建立一個M2M關係(Relation.1)來記錄。 * 因為 library function 自上傳後,內容就固定,因此不需要額外紀錄`Device`與`LibraryFunction`的關係,可以透過 `Device` -> `DeviceHasLibrary` -> `Library` -> `LibraryFunction` 的關係,來獲得某 device 有哪些的 library function。 ### Device、DF 與 SaFunction的關係 * 在每個`Device`建立時,DeviceTalk會為其新增他的DM中的所有DF,紀錄在 `DeviceDf`(table.g) 中。 * 例如: 有個`DM`包含`DF1`, `DF2`, `DF3`,在建立時,這三個DF都會被建立,即便說此 Device,對應在 IoTtalk Project 上的 Device Object,只使用了`DF1`。而 DeviceTalk GUI 顯示的 DF 會與 Device Object 相同。 * 在同一個 Device 中,允許超過一個 DF 使用相同的 SaFunction,但可以搭配不同的 variable setup 內容,而 `DeviceDfHasSaFunction`(table.h) 就是用來紀錄這些差異,除了 variable setup 外,同時也記錄了每個 DF 選擇哪個 SaFunction。 * 為何有了`DF`與`SaFunction`的關係(Relation.3~5),還需要紀錄 Relation.1呢? 因為 Relation.3~5 只紀錄各DF選擇過哪些`SaFunction`,Relation.1 還紀錄其他沒被使用的`SaFunction`,在儲存成 device library 時會一起被紀錄,供其他使用者使用。 ### 儲存 Device 時產生的 Device Library 在每個 device 儲存時,除了更新上述對應的資料,也會以該 device 為名,建立一個 library,這個 library 屬於`DeviceLibrary`。 #### DF * 新建立的`DeviceLibrary`會複製`Device`中所有的 DF 關聯資訊與 SaFunction 關聯資訊。其對應關係分別是: * `DeviceDf`(table.g) -> `DeviceLibraryDf`(table.i) * `DeviceDfHasSaFunction`(table.h) -> `DeviceLibraryDfHasSaFunction`(table.j) * Relation.1 -> Relation.2 * `DeviceLibrary`做為 library 之所以會需要紀錄 DF 資訊,是方便下次其他使用者使用此 `DeviceLibrary`,能匯入 DF 與 SaFunction 資訊,縮短使用者設定的時間。 * 因為`DeviceLibrary`對於 DeviceTalk GUI,是不分 Device Model 的,因此當`DeviceLibrary`被更新時,DF 資訊會疊加。 #### Library * 由於`Device`可以有 dependency library,同理`DeviceLibrary`也需紀錄其 dependency library。儲存時的邏輯如下 * 將`Device`與`Library`的關係(Relation.10~11),記錄在新的`DeviceLibrary`的 Relation.12 中。 * 將`Device`與`DeviceLibrary`的關係,為避免過多層的巢狀呼叫,不紀錄,而是直接合併其中所有的`SaFunction`,原則上取聯集,當兩個`SaFunction`的`DfType`與`name`相同時,以較新的為準。