简易データベースの種類(定制固件专属)是一个轻量级、无文件系统的エンベデッド·インデータベースの種類:在 Flash 里划一块连续エリア,按固定長さ记录存構造化データ(参数設定、事件日志、运行记录),掉电不丢,サポート运行时按需初期化。データ記録控件用「Customization」データ源モード对接,実装增删改查全流程。
1. ⚠️ Flash アドレス规划(不看会变砖)
简易データベースの種類直接操作 Flash,ない文件系统絶縁机制,flashaddr 開始アドレス必须严格避开四类高风险エリア:
- 工程リソース存储区
- 资料采样块存储区
- 操作记录块存储区
- OTA アップグレード备份エリア
总占用空间 = dataRowSize × maxCount,规划アドレス时把这段空间算进去,别和别的功能打架。
2. API 总表
| 函数 | parameter | 説明 |
|---|---|---|
easydb_open(flashaddr, createIfNotExist, dataRowSize, maxCount) | flashaddr Flash starting address;createIfNotExist 0=仅打开/1=不存在则作成;dataRowSize ≥1;maxCount 最大条数 | 打开或作成データベースの種類,戻る句柄(非 0 成功,0 失敗) |
easydb_close(db) | 句柄 | 关闭データベースの種類,释放リソース |
easydb_get_count(db) | 句柄 | 当前有效记录数 |
easydb_get(db, idx) | idx 从 0 开始 | 读指定索引记录,成功戻るストリング·ストリング,失敗 nil |
easydb_add(db, dataset) | ストリング·ストリングデータ | 末尾追加一件のレコード |
easydb_update(db, idx, dataset) | idx + 新内容 | 更新指定记录,dataset 長さ必须严格等于 dataRowSize |
easydb_del(db, idx) | idx | 削除指定记录 |
easydb_clear(db) | 句柄 | クリアすべての记录 |
3. データ記録控件「Customization」モード
データ来源设为Customization时,系统不知道有多少行データ,必须由2つ回调提供:
- 记录数量回调
on_get_record_count(screen_id, control_id):戻る总行数,内部调 easydb_get_count(g_db_handle) - 记录内容回调
on_get_record_row(screen_id, control_id, row):戻る第 row 行的ストリング·ストリング内容
function on_get_record_count(screen_id, control_id)
if screen_id == 0 and control_id == 1 then
return db.getCnt(g_db_handle)
end
end
function on_get_record_row(screen_id, control_id, row)
local ret, msg = db.get(g_db_handle, row)
if ret == 0 then
return msg
end
end控件設定:データ来源=Customization、文字编码=UTF8、翻页控制√、控制アドレス LW4000、选中行通知√(LW4004,UINT32)——选中某行时索引写进 LW4004,增删改都靠它ポジショニング。
4. 应用:db.lua 句柄封装 + 增删改查
4.1 初期化(on_init)
function on_init()
dofile("db.lua")
_EN_ON_UPDATA_API_ = 0
-- 10MB start、不存在则作成、单条1000バイト、最多1000条
g_db_handle = db.open(10*1024*1024, 1, 1000, 1000)
if g_db_handle == 0 then
print("ERROR: 无法打开データベースの種類!")
return
end
db.clear(g_db_handle) -- クリア旧データ(可选)
db.add(g_db_handle, "Alice;Engineer;30")
db.add(g_db_handle, "Bob;Technician;25")
db.add(g_db_handle, "Charlie;Manager;40")
db.add(g_db_handle, "Harden;Basketball players;36")
_EN_ON_UPDATA_API_ = 1
end记录格式「Name;职业;年龄」,英文分号分隔,和表格控件解析ルール一致,直接マッピング多列。
4.2 增删改(LW5000 按键分发)
function on_update(slave, vtype, addr)
if addr == 0x4004 then -- 选中行通知
local idx = get_uint32(VT_LW, addr)
local ret, msg = db.get(g_db_handle, idx)
if ret == 0 then
local parts = my_split(msg, ";")
if parts ~= nil then
set_uint16(VT_LW, 0x4530, idx) -- 记录当前选中索引
set_string(VT_LW, 0x4500, (parts[1] == nil) and "--" or parts[1])
set_string(VT_LW, 0x4510, (parts[2] == nil) and "--" or parts[2])
set_string(VT_LW, 0x4520, (parts[3] == nil) and "--" or parts[3])
end
show_dialog(1, 232, 33, 50) -- 弹窗表示詳細
end
elseif addr == 0x5000 then
local key = get_uint16(VT_LW, addr)
if key == 0 then -- 追加
local name = get_string(VT_LW, 0x5010)
local position = get_string(VT_LW, 0x5020)
local age = get_string(VT_LW, 0x5030)
db.add(g_db_handle, name..";"..position..";"..age..";")
elseif key == 1 then -- 修改(改选中行)
local name = get_string(VT_LW, 0x4500)
local position = get_string(VT_LW, 0x4510)
local age = get_string(VT_LW, 0x4520)
local idx = get_uint16(VT_LW, 0x4530)
db.modify(g_db_handle, idx, name..";"..position..";"..age..";")
elseif key == 2 then -- Delete(删选中行)
local idx = get_uint16(VT_LW, 0x4530)
db.del(g_db_handle, idx)
end
end
enddb.lua 封装层每个函数都做句柄チェック + 索引越界チェック(idx = count 戻る -2),这是句柄驱动设计的標準姿势:不合法就直接戻るエラー·コード,绝不往下传。
整理自 广州大彩科技 VisualHMI 开发ドキュメント(hmi-doc.gz-dc.com)LUA Tutorial「简易データベースの種類」,著作権は大彩科技すべての。
Leave a Reply