add calendar mode for html

This commit is contained in:
Shuanglei Tao
2025-02-05 23:32:57 +08:00
parent 705d131f36
commit 77f7aae4e8
3 changed files with 50 additions and 17 deletions

View File

@@ -4,7 +4,7 @@ on:
push:
branches: ["main"]
paths:
- "html/*"
- "html/**"
workflow_dispatch:
permissions:

View File

@@ -36,7 +36,7 @@
<div class="main">
<h3>4.2 寸电子墨水屏蓝牙控制器nRF51</h3>
<fieldset>
<legend>蓝牙</legend>
<legend>蓝牙连接</legend>
<div style="display: flex; justify-content: space-between;">
<div>
<button id="connectbutton" type="button" class="primary" onclick="preConnect()">连接</button>
@@ -57,16 +57,19 @@
</fieldset>
<fieldset>
<legend>传图</legend>
<legend>屏幕控制</legend>
<div style="margin-bottom: 10px; display: flex; justify-content: space-between;">
<div>
<button id="clearcanvasbutton" type="button" class="secondary" onclick="clear_canvas()">清除画布</button>
<button id="sendimgbutton" type="button" class="primary" onclick="sendimg()">发送图片</button>
<label for="interleavedcount" style="margin-left: 20px;">确认间隔</label>
<input type="number" id="interleavedcount" value="50">
<input type="number" id="interleavedcount" value="50" min="0" max="500">
</div>
<div>
<button id="clearscreenbutton" type="button" class="secondary" onclick="clearscreen()">清除屏幕</button>
<button id="synctimebutton" type="button" class="primary" onclick="syncTime()">日历模式</button>
</div>
<div>
<button id="clearscreenbutton" type="button" class="secondary" onclick="clearScreen()">清除屏幕</button>
<input type="text" id="cmdTXT" value="">
<button id="sendcmdbutton" type="button" class="primary" onclick="sendcmd()">发送命令</button>
</div>
@@ -110,6 +113,7 @@
<li><b>驱动选择:</b>黑白屏可尝试 EPD_4in2 / EPD_4in2_V2, 三色屏选择 EPD_4in2b_V2 (选错驱动可能会导致任何未知的异常,重启即可恢复)</li>
<li><b>引脚配置:</b>格式为十六进制顺序MOSI/SCLK/CS/DC/ST/BUSY/BS必须按此顺序包含完整的 7 个引脚配置(没有用到的引脚可配置为 <code>FF</code></li>
<li><b>确认间隔: </b>这个间隔指的是数据包数量间隔,即发送此数量的不确认响应的数据包后才发送一次需确认响应的数据包。加大此值可优化传图速度,但是丢包风险也更大(你可能会发现图片有部分位置显示不正常,此时需调小这个值)。
<li><b>日历模式: </b>点击“日历模式”按钮将自动从浏览器同步时间到墨水屏,并切换到日历显示。</li>
<li>
<b>指令列表(指令和参数全部要使用十六进制):</b>
<ul>
@@ -124,6 +128,10 @@
<li><code>06</code>: 屏幕睡眠</li>
</ul>
</li>
<li>日历模式:
<ul>
<li><code>20</code>+<code>UNIX 时间戳</code>: 同步时间并开启日历模式</li>
</ul>
<li>系统相关:
<ul>
<li><code>90</code>+<code>配置</code>: 写入配置信息(重启生效,格式参考源码 <code>epd_config_t</code></li>

View File

@@ -17,6 +17,8 @@ const EpdCmd = {
DISPLAY: 0x05,
SLEEP: 0x06,
SET_TIME: 0x20,
SET_CONFIG: 0x90,
SYS_RESET: 0x91,
SYS_SLEEP: 0x92,
@@ -31,7 +33,7 @@ function resetVariables() {
}
async function handleError(error) {
console.log(error);
console.error(error);
resetVariables();
if (bleDevice == null)
return;
@@ -48,22 +50,30 @@ async function handleError(error) {
async function write(cmd, data, withResponse=true) {
if (!epdCharacteristic) {
addLog("服务不可用,请检查蓝牙连接");
return;
return false;
}
let payload = [cmd];
if (data) {
if (typeof data == 'string') data = hex2bytes(data);
if (data instanceof Uint8Array) data = Array.from(data);
payload.push(...data)
};
}
if (payload.length > MAX_PACKET_SIZE) {
throw new Error("BLE packet too large!");
addLog("BLE packet too large!");
return false;
}
addLog(`<span class="action">⇑</span> ${bytes2hex(payload)}`);
if (withResponse)
await epdCharacteristic.writeValueWithResponse(Uint8Array.from(payload));
else
await epdCharacteristic.writeValueWithoutResponse(Uint8Array.from(payload));
try {
if (withResponse)
await epdCharacteristic.writeValueWithResponse(Uint8Array.from(payload));
else
await epdCharacteristic.writeValueWithoutResponse(Uint8Array.from(payload));
} catch (e) {
console.error(e);
if (e.message) addLog(e.message);
return false;
}
return true;
}
async function epdWrite(cmd, data) {
@@ -95,7 +105,21 @@ async function setDriver() {
await write(EpdCmd.INIT, document.getElementById("epddriver").value);
}
async function clearscreen() {
async function syncTime() {
const timestamp = new Date().getTime() / 1000;
const data = new Uint8Array([
(timestamp >> 24) & 0xFF,
(timestamp >> 16) & 0xFF,
(timestamp >> 8) & 0xFF,
timestamp & 0xFF,
-(new Date().getTimezoneOffset() / 60)
]);
if(await write(EpdCmd.SET_TIME, data)) {
addLog("日历模式:时间已同步!需要一定时间刷新,请耐心等待。");
}
}
async function clearScreen() {
if(confirm('确认清除屏幕内容?')) {
await write(EpdCmd.CLEAR);
}
@@ -163,6 +187,7 @@ function updateButtonStatus() {
const status = connected ? null : 'disabled';
document.getElementById("reconnectbutton").disabled = (gattServer == null || gattServer.connected) ? 'disabled' : null;
document.getElementById("sendcmdbutton").disabled = status;
document.getElementById("synctimebutton").disabled = status;
document.getElementById("clearscreenbutton").disabled = status;
document.getElementById("sendimgbutton").disabled = status;
document.getElementById("setDriverbutton").disabled = status;
@@ -178,18 +203,18 @@ function disconnect() {
async function preConnect() {
if (gattServer != null && gattServer.connected) {
if (bleDevice != null && bleDevice.gatt.connected) {
await write(EpdCmd.SLEEP);
bleDevice.gatt.disconnect();
}
}
else {
connectTrys = 0;
reconnectTrys = 0;
try {
bleDevice = await navigator.bluetooth.requestDevice({
optionalServices: ['62750001-d828-918d-fb46-b6c11c675aec'],
acceptAllDevices: true
});
} catch (e) {
console.error(e);
if (e.message) addLog(e.message);
return;
}
@@ -204,7 +229,7 @@ async function preConnect() {
}
async function reConnect() {
connectTrys = 0;
reconnectTrys = 0;
if (bleDevice != null && bleDevice.gatt.connected)
bleDevice.gatt.disconnect();
resetVariables();