add/tested history, clock
This commit is contained in:
parent
ad38d7b758
commit
00013d3da7
20 changed files with 9219 additions and 7022 deletions
|
|
@ -160,7 +160,7 @@ SRCS += $(SDK_PATH)/lib/ble_host/gap_devmgr.c
|
|||
SRCS += $(SDK_PATH)/lib/ble_host/gap_linkmgr.c
|
||||
SRCS += $(SDK_PATH)/lib/ble_host/gap_peridevmgr.c
|
||||
SRCS += $(SDK_PATH)/lib/ble_host/gap_perilinkmgr.c
|
||||
SRCS += $(SDK_PATH)/lib/ble_host/gap_simpletask.c
|
||||
#SRCS += $(SDK_PATH)/lib/ble_host/gap_simpletask.c
|
||||
SRCS += $(SDK_PATH)/lib/ble_host/gap_task.c
|
||||
SRCS += $(SDK_PATH)/lib/ble_host/gatt_client.c
|
||||
SRCS += $(SDK_PATH)/lib/ble_host/gatt_server.c
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -18,7 +18,7 @@ extern "C"
|
|||
*/
|
||||
// A complete list of interface commands for different devices.
|
||||
// Not all commands are supported by a specific device (!)
|
||||
enum CMD_ID_KEYS {
|
||||
typedef enum {
|
||||
CMD_ID_DEVID = 0x00, // Get dev id, version, services
|
||||
CMD_ID_DNAME = 0x01, // Get/Set device name, "\0" - default: THB2_xxxx
|
||||
CMD_ID_GDEVS = 0x02, // Get address devices
|
||||
|
|
@ -65,7 +65,7 @@ enum CMD_ID_KEYS {
|
|||
CMD_ID_LR_RESET = 0xDD, // Reset Long Range
|
||||
CMD_ID_DEBUG = 0xDE // Test/Debug
|
||||
|
||||
};
|
||||
} CMD_ID_KEYS;
|
||||
|
||||
// supported services by the device
|
||||
typedef struct _dev_services_t{
|
||||
|
|
|
|||
|
|
@ -86,6 +86,7 @@ void test_config(void) {
|
|||
gapRole_MinConnInterval = periConnParameters.intervalMin = DEFAULT_DESIRED_MIN_CONN_INTERVAL;
|
||||
gapRole_MaxConnInterval = periConnParameters.intervalMax = DEFAULT_DESIRED_MAX_CONN_INTERVAL;
|
||||
gapRole_SlaveLatency = periConnParameters.latency = cfg.connect_latency;
|
||||
|
||||
periConnParameters.timeout = (cfg.connect_latency + 1) * 3 * 4;
|
||||
if(periConnParameters.timeout > 2048)
|
||||
periConnParameters.timeout = 2048; // 20.48 sec мax
|
||||
|
|
|
|||
|
|
@ -101,7 +101,7 @@ const uint8_t lcd_init_cmd[] = {
|
|||
* 0x5 = "°F"
|
||||
* 0x6 = " ="
|
||||
* 0x7 = "°E" */
|
||||
void show_temp_symbol(uint8_t symbol) {
|
||||
void show_temp_symbol(CLD_TEMP_SYMBOL symbol) {
|
||||
display_buff[2] &= ~BIT(3);
|
||||
display_buff[3] &= ~(BIT(7)|BIT(5)) ;
|
||||
display_buff[2] |= (symbol << 2) & BIT(3);
|
||||
|
|
@ -167,7 +167,7 @@ void show_big_number_x10(int16_t number) {
|
|||
if (number > 99) display_buff[0] |= display_numbers[number / 100 % 10];
|
||||
if (number > 9) display_buff[1] |= display_numbers[number / 10 % 10];
|
||||
else display_buff[1] |= LCD_SYM_0; // "0"
|
||||
display_buff[2] = display_numbers[number %10];
|
||||
display_buff[2] |= display_numbers[number %10];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -39,6 +39,23 @@
|
|||
extern uint8_t lcd_i2c_addr; // LCD controller I2C address
|
||||
extern uint8_t display_buff[LCD_BUF_SIZE];
|
||||
|
||||
|
||||
/* 0x0 = " "
|
||||
* 0x1 = "°Г"
|
||||
* 0x2 = " _"
|
||||
* 0x3 = "°C"
|
||||
* 0x4 = " -"
|
||||
* 0x5 = "°F"
|
||||
* 0x6 = " ="
|
||||
* 0x7 = "°E" */
|
||||
typedef enum {
|
||||
CLD_TSYMBOL_NONE, // " "
|
||||
CLD_TSYMBOL_C = 3, // "°C"
|
||||
CLD_TSYMBOL_F = 5, // "°F"
|
||||
CLD_TSYMBOL_EQ = 6, // " ="
|
||||
CLD_TSYMBOL_E = 7 // "°E"
|
||||
} CLD_TEMP_SYMBOL;
|
||||
|
||||
void init_lcd(void);
|
||||
void update_lcd(void);
|
||||
void show_small_number(int16_t number, bool percent);
|
||||
|
|
@ -46,6 +63,6 @@ void show_big_number_x10(int16_t number);
|
|||
void show_battery_symbol(bool state);
|
||||
void show_ble_symbol(bool state);
|
||||
void show_smiley(uint8_t state);
|
||||
void show_temp_symbol(uint8_t symbol);
|
||||
void show_temp_symbol(CLD_TEMP_SYMBOL symbol);
|
||||
|
||||
#endif /* _LCD_TH05_H_ */
|
||||
|
|
|
|||
|
|
@ -158,7 +158,6 @@ int send_memo_blk(uint8_t * send_buf) {
|
|||
send_buf[1] = 0;
|
||||
send_buf[2] = 0;
|
||||
olen = 3;
|
||||
// bls_pm_setManualLatency(cfg.connect_latency);
|
||||
rd_memo.cnt = 0;
|
||||
} else {
|
||||
send_buf[1] = rd_memo.cur;
|
||||
|
|
|
|||
|
|
@ -46,6 +46,24 @@
|
|||
GLOBAL VARIABLES
|
||||
*/
|
||||
|
||||
/*
|
||||
extern l2capSegmentBuff_t l2capSegmentPkt[MAX_NUM_LL_CONN];
|
||||
uint8_t notify_enable_TaskID;
|
||||
extern uint16 gapRole_ConnectionHandle;
|
||||
// add event free buf
|
||||
uint16 _HCI_ProcessEvent( uint8 task_id, uint16 events ) {
|
||||
uint16 ret = HCI_ProcessEvent(task_id, events);
|
||||
if(ret == 0) {
|
||||
if(notify_enable_TaskID) {
|
||||
//&& l2capSegmentPkt[gapRole_ConnectionHandle].fragment
|
||||
//&& l2capSegmentPkt[gapRole_ConnectionHandle].depth < 3) {
|
||||
osal_set_event(notify_enable_TaskID, WRK_NOTIFY_EVT);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
*/
|
||||
|
||||
// The order in this table must be identical to the task initialization calls below in osalInitTask.
|
||||
const pTaskEventHandlerFn tasksArr[] =
|
||||
{
|
||||
|
|
@ -73,7 +91,6 @@ uint16* tasksEvents;
|
|||
/*********************************************************************
|
||||
FUNCTIONS
|
||||
*********************************************************************/
|
||||
|
||||
/*********************************************************************
|
||||
@fn osalInitTasks
|
||||
|
||||
|
|
|
|||
|
|
@ -25,6 +25,8 @@
|
|||
#include "cmd_parser.h"
|
||||
#include "ble_ota.h"
|
||||
#include "logger.h"
|
||||
#include "hci.h"
|
||||
#include "lcd_th05.h"
|
||||
|
||||
/*********************************************************************
|
||||
* MACROS
|
||||
|
|
@ -463,23 +465,32 @@ void new_ota_data(void) {
|
|||
}
|
||||
#endif
|
||||
|
||||
|
||||
#if (DEV_SERVICES & SERVICE_HISTORY)
|
||||
void wrk_notify(void) {
|
||||
gattServerInfo_t* pServer;
|
||||
attHandleValueNoti_t noti;
|
||||
if (gattGetServerStatus( gapRole_ConnectionHandle, &pServer ) != bleTimeout) {
|
||||
noti.len = 0;
|
||||
#if (DEV_SERVICES & SERVICE_HISTORY)
|
||||
// if(rd_memo.cnt)
|
||||
noti.len = send_memo_blk(noti.value);
|
||||
#endif
|
||||
if(noti.len) {
|
||||
noti.handle = simpleProfileAttrTbl[CDM_DATA_ATTR_IDX].handle;
|
||||
if(ATT_HandleValueNoti(gapRole_ConnectionHandle, ¬i) != SUCCESS || noti.len <= 3)
|
||||
return;
|
||||
osal_set_event(simpleBLEPeripheral_TaskID, WRK_NOTIFY_EVT);
|
||||
} else
|
||||
return;
|
||||
// gattStoreServerInfo( pServer, simpleBLEPeripheral_TaskID );
|
||||
noti.len = 0;
|
||||
if(rd_memo.cnt) {
|
||||
while(1) { // 4096 memo 43 sec [memo = 13 bytes] -> 1238 bytes/s
|
||||
noti.handle = simpleProfileAttrTbl[CDM_DATA_ATTR_IDX].handle;
|
||||
noti.len = send_memo_blk(noti.value);
|
||||
if(noti.len) {
|
||||
bStatus_t err = ATT_HandleValueNoti(gapRole_ConnectionHandle, ¬i);
|
||||
if(err == bleMemAllocError
|
||||
|| err == MSG_BUFFER_NOT_AVAIL
|
||||
|| err == HCI_ERROR_CODE_MEM_CAP_EXCEEDED) {
|
||||
rd_memo.cur--;
|
||||
osal_start_timerEx(simpleBLEPeripheral_TaskID, WRK_NOTIFY_EVT, (DEFAULT_DESIRED_MIN_CONN_INTERVAL *125)/100);
|
||||
break;
|
||||
} else if (err != SUCCESS || noti.len <= 3)
|
||||
break;
|
||||
} else
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else
|
||||
osal_start_timerEx(simpleBLEPeripheral_TaskID, WRK_NOTIFY_EVT, 30);
|
||||
osal_start_timerEx(simpleBLEPeripheral_TaskID, WRK_NOTIFY_EVT, 30);
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -109,7 +109,7 @@ void chow_measure(void) {
|
|||
show_big_number_x10(measured_data.temp/10);
|
||||
show_small_number(measured_data.humi/100, true);
|
||||
show_battery_symbol(measured_data.battery < 20);
|
||||
show_temp_symbol(3);
|
||||
show_temp_symbol(CLD_TSYMBOL_C);
|
||||
#else
|
||||
show_big_number_x10(measured_data.battery_mv/100);
|
||||
show_small_number((measured_data.battery > 99)? 99 : measured_data.battery, true);
|
||||
|
|
@ -159,6 +159,7 @@ static void set_mac(void)
|
|||
}
|
||||
}
|
||||
set_def_name(ownPublicAddr);
|
||||
// TODO: pGlobal_config[MAC_ADDRESS_LOC]
|
||||
}
|
||||
|
||||
static void set_serial_number(void)
|
||||
|
|
@ -484,9 +485,12 @@ void SimpleBLEPeripheral_Init( uint8 task_id )
|
|||
// HCI_LE_SetDefaultPhyMode(0,0xff,0x01,0x01);
|
||||
|
||||
#ifdef MTU_SIZE
|
||||
#if MTU_SIZE > ATT_MAX_MTU_SIZE
|
||||
#error "MTU_SIZE > 517"
|
||||
#endif
|
||||
ATT_SetMTUSizeMax(MTU_SIZE);
|
||||
#else
|
||||
ATT_SetMTUSizeMax(23);
|
||||
ATT_SetMTUSizeMax(ATT_MTU_SIZE_MIN);
|
||||
#endif
|
||||
// Setup a delayed profile startup
|
||||
osal_set_event( simpleBLEPeripheral_TaskID, SBP_START_DEVICE_EVT );
|
||||
|
|
@ -604,11 +608,13 @@ uint16 BLEPeripheral_ProcessEvent( uint8 task_id, uint16 events )
|
|||
// return unprocessed events
|
||||
return ( events ^ SBP_START_DEVICE_EVT );
|
||||
}
|
||||
#if (DEV_SERVICES & SERVICE_HISTORY)
|
||||
if(events & WRK_NOTIFY_EVT) {
|
||||
LOG("Wrk notify events\n");
|
||||
wrk_notify();
|
||||
return(events ^ WRK_NOTIFY_EVT);
|
||||
}
|
||||
#endif
|
||||
if(events & SBP_CMDDATA) {
|
||||
LOG("CMD data events\n");
|
||||
new_cmd_data();
|
||||
|
|
@ -636,7 +642,6 @@ static void simpleBLEPeripheral_ProcessOSALMsg( osal_event_hdr_t *pMsg )
|
|||
switch ( pMsg->event ){
|
||||
case HCI_GAP_EVENT_EVENT:{
|
||||
switch( pMsg->status ){
|
||||
|
||||
case HCI_COMMAND_COMPLETE_EVENT_CODE:
|
||||
#if DEBUG_INFO
|
||||
pHciMsg = (hciEvt_CmdComplete_t *)pMsg;
|
||||
|
|
|
|||
799
bthome_phy6222/web/GraphMemo.html
Normal file
799
bthome_phy6222/web/GraphMemo.html
Normal file
File diff suppressed because one or more lines are too long
696
bthome_phy6222/web/GraphPhy6.html
Normal file
696
bthome_phy6222/web/GraphPhy6.html
Normal file
File diff suppressed because one or more lines are too long
621
bthome_phy6222/web/phy6222.html
Normal file
621
bthome_phy6222/web/phy6222.html
Normal file
|
|
@ -0,0 +1,621 @@
|
|||
<html class="phy6222Class"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<link rel="stylesheet" href="styles.css">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>PHY62x2-BTHome тестовая версия</title>
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
//BLE values
|
||||
const FLASH_SIZE = 0x80000;
|
||||
var bluetoothDevice, gattServer, otaCharacteristic, myCharacteristic;
|
||||
//Firmware values
|
||||
var firmwareArray = "",
|
||||
startTime = 0,
|
||||
flgRdFF = false,
|
||||
blockCount = 0;
|
||||
//Connection values
|
||||
var connectTrys = 0;
|
||||
|
||||
var $ = function(id) { return document.getElementById(id);}
|
||||
|
||||
function resetVariables() {
|
||||
busy = false;
|
||||
gattServer = null;
|
||||
Theservice = null;
|
||||
otaCharacteristic = null;
|
||||
myCharacteristic = null;
|
||||
$('btnDisconnect').disabled = true;
|
||||
$('btnReadFF').disabled = true;
|
||||
$('btnReadAddr').disabled = true;
|
||||
$('btnSave').disabled = true;
|
||||
$('btnStartDFU').disabled = true;
|
||||
$('btnSendData').disabled = true;
|
||||
$('btnSendCommand').disabled = true;
|
||||
// showState("Ожидание соединения с устройством")
|
||||
}
|
||||
|
||||
function handleError(text) {
|
||||
showError(text);
|
||||
resetVariables();
|
||||
if (connectTrys < 5) {
|
||||
connectTrys++;
|
||||
addLog("Переподключение " + connectTrys + " из " + 5);
|
||||
doConnect();
|
||||
} else {
|
||||
addLog("Подключиться не удалось!");
|
||||
connectTrys = 0;
|
||||
}
|
||||
}
|
||||
|
||||
function doConnect() {
|
||||
showState("Ожидание соединения с " + bluetoothDevice.name)
|
||||
bluetoothDevice.gatt.connect().then(server => {
|
||||
console.log("Найден GATT сервер");
|
||||
gattServer = server;
|
||||
return gattServer.getPrimaryService(0xfff0);
|
||||
}).then(service => {
|
||||
console.log("Найден Main сервис");
|
||||
Theservice = service;
|
||||
return service.getCharacteristic(0xfff3);
|
||||
}).then(characteristic => {
|
||||
console.log("Найдена OTA характеристика");
|
||||
otaCharacteristic = characteristic;
|
||||
return Theservice.getCharacteristic(0xfff4);
|
||||
}).then(characteristic => {
|
||||
console.log("Найдена CMD характеристика");
|
||||
myCharacteristic = characteristic;
|
||||
myCharacteristic.readValue().then(value => {
|
||||
if(value.byteLength >= 10)
|
||||
addLog("DevCfg: " + dump8(value, value.byteLength));
|
||||
//flash_buf = new Uint8Array(FLASH_SIZE);
|
||||
myCharacteristic.addEventListener('characteristicvaluechanged', event => customBlkParse(event.target.value));
|
||||
myCharacteristic.startNotifications().then(_ => {
|
||||
showState("Устройство подключено.");
|
||||
$('btnDisconnect').disabled = false;
|
||||
$('btnReconnect').disabled = false;
|
||||
$('btnSendCommand').disabled = false;
|
||||
$('btnReadFF').disabled = false;
|
||||
$('btnReadAddr').disabled = false;
|
||||
$('btnSendData').disabled = false;
|
||||
$('btnStartDFU').disabled = false; })
|
||||
})
|
||||
}).catch(handleError);
|
||||
}
|
||||
|
||||
function onDisconnected() {
|
||||
resetVariables();
|
||||
showState('Устройство отключено.');
|
||||
}
|
||||
|
||||
function connect() {
|
||||
var deviceOptions = {
|
||||
optionalServices: [0xfff0],
|
||||
services: [0x180a, 0x181c, 0x181e, 0xfff0],
|
||||
acceptAllDevices: true };
|
||||
const namePrefix = $('inpNamePrefix').value;
|
||||
if (namePrefix) {
|
||||
deviceOptions.acceptAllDevices = false;
|
||||
deviceOptions.filters = namePrefix.split(",")
|
||||
.map((x) => ({ namePrefix: x }));
|
||||
} else {
|
||||
deviceOptions.acceptAllDevices = false;
|
||||
deviceOptions.filters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz_#@!*0123456789';,.<>{}[]"
|
||||
.split("")
|
||||
.map((x) => ({ namePrefix: x }));
|
||||
}
|
||||
if (bluetoothDevice != null) bluetoothDevice.gatt.disconnect();
|
||||
resetVariables();
|
||||
$('btnReconnect').disabled = true;
|
||||
|
||||
showState("Поиск устройств");
|
||||
connectTrys = 0;
|
||||
navigator.bluetooth.requestDevice(deviceOptions).then(device => {
|
||||
bluetoothDevice = device;
|
||||
bluetoothDevice.addEventListener('gattserverdisconnected', onDisconnected);
|
||||
// addLog("Connecting to: " + bluetoothDevice.name);
|
||||
doConnect();
|
||||
}).catch(handleError);
|
||||
}
|
||||
|
||||
|
||||
function disconnect() {
|
||||
addLog("Отключение");
|
||||
if (bluetoothDevice != null) bluetoothDevice.gatt.disconnect();
|
||||
}
|
||||
|
||||
function reconnect() {
|
||||
addLog("Переподключение");
|
||||
if (bluetoothDevice != null) bluetoothDevice.gatt.disconnect();
|
||||
connectTrys = 0;
|
||||
doConnect();
|
||||
}
|
||||
|
||||
function startDFU() {
|
||||
addLog("Start DFU");
|
||||
updateBegin();
|
||||
}
|
||||
|
||||
function addLog(text) {
|
||||
var stime = new Date().toLocaleTimeString();
|
||||
var string = stime + ": " + text;
|
||||
console.log(string)
|
||||
$("log").innerHTML += string + "<br>";
|
||||
}
|
||||
|
||||
function clearLog() {
|
||||
$("log").innerHTML = "";
|
||||
}
|
||||
|
||||
function showState(text) {
|
||||
// console.log("Status: " + status);
|
||||
let s = "Состояние: " + text;
|
||||
document.getElementById("lblStatus").className = "shadowbox";
|
||||
$("lblStatus").innerHTML = s;
|
||||
addLog(text);
|
||||
}
|
||||
|
||||
function showError(text) {
|
||||
// console.log("Status: " + status);
|
||||
let s = "Ошибка: " + text;
|
||||
document.getElementById("lblStatus").className = "shadowerror";
|
||||
$("lblStatus").innerHTML = s;
|
||||
addLog(text);
|
||||
}
|
||||
|
||||
function showProgress(text) {
|
||||
document.getElementById("lblStatus").className = "shadowprogress";
|
||||
$("lblStatus").innerHTML = text;
|
||||
}
|
||||
|
||||
function updateFail(err) {
|
||||
let s = err + ". Update failed";
|
||||
showError(s);
|
||||
}
|
||||
|
||||
function decimalToHex(d, padding) {
|
||||
var hex = Number(d).toString(16);
|
||||
while (hex.length < 4) {
|
||||
hex = "0" + hex;
|
||||
}
|
||||
return hex;
|
||||
}
|
||||
|
||||
function hexToBytes(hex) {
|
||||
for (var bytes = [], c = 0; c < hex.length; c += 2)
|
||||
bytes.push(parseInt(hex.substr(c, 2), 16));
|
||||
return new Uint8Array(bytes);
|
||||
}
|
||||
|
||||
function bytesToHex(data) {
|
||||
return new Uint8Array(data).reduce(function(memo, i) {
|
||||
return memo + ("0" + i.toString(16)).slice(-2);
|
||||
}, "");
|
||||
}
|
||||
|
||||
function crc16_modbus(buffer) {
|
||||
var crc = 0xFFFF;
|
||||
var odd;
|
||||
for (var i = 0; i < buffer.length; i++) {
|
||||
crc = crc ^ buffer[i];
|
||||
for (var j = 0; j < 8; j++) {
|
||||
odd = crc & 0x0001;
|
||||
crc = crc >> 1;
|
||||
if (odd) {
|
||||
crc = crc ^ 0xA001;
|
||||
}
|
||||
}
|
||||
}
|
||||
return crc;
|
||||
};
|
||||
|
||||
function getHexCRC(data) {
|
||||
var tempCRC = decimalToHex(crc16_modbus(hexToBytes(data)));
|
||||
return tempCRC.substring(2, 4) + tempCRC.substring(0, 2);
|
||||
}
|
||||
|
||||
function makeRandomID(length) {
|
||||
var result = '';
|
||||
var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
|
||||
var charactersLength = characters.length;
|
||||
for (var i = 0; i < length; i++) {
|
||||
result += characters.charAt(Math.floor(Math.random() * charactersLength));
|
||||
}
|
||||
return bytesToHex(new TextEncoder("utf-8").encode(result));
|
||||
}
|
||||
|
||||
function hex(number, len) {
|
||||
var str = (number.toString(16)).toUpperCase();
|
||||
while (str.length < len) str = '0' + str;
|
||||
return str;
|
||||
}
|
||||
|
||||
function hexToBytes(hex) {
|
||||
for (var bytes = [], c = 0; c < hex.length; c += 2)
|
||||
bytes.push(parseInt(hex.substr(c, 2), 16));
|
||||
return new Uint8Array(bytes);
|
||||
}
|
||||
|
||||
function dump(ar, len) {
|
||||
let s = '';
|
||||
for(let i=0; i < len; i++) {
|
||||
s += hex(ar[i],2);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
function dump8(ar, len) {
|
||||
let s = '';
|
||||
for(let i=0; i < len; i++) {
|
||||
s += hex(ar.getUint8(i),2);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
function hex2ascii(hexx) {
|
||||
var hex = hexx.toString();
|
||||
var str = '';
|
||||
for (var i = 0;
|
||||
(i < hex.length && hex.substr(i, 2) !== '00'); i += 2)
|
||||
str += String.fromCharCode(parseInt(hex.substr(i, 2), 16));
|
||||
return str;
|
||||
}
|
||||
|
||||
function updateBegin() {
|
||||
if (blockCount <= 0) {
|
||||
showError("Не выбран файл!");
|
||||
return;
|
||||
}
|
||||
|
||||
setTimeout(function() {
|
||||
otaCharSend("00ff").then(function(character) {
|
||||
otaCharSend("01ff").then(function(character) {
|
||||
setTimeout(function() {
|
||||
startTime = new Date().getTime();
|
||||
sendOTAblock(0);
|
||||
}, 300);
|
||||
}).catch(function(err) {
|
||||
updateFail(err);
|
||||
});
|
||||
}).catch(function(err) {
|
||||
updateFail(err);
|
||||
});
|
||||
}, 500);
|
||||
}
|
||||
|
||||
function sendOTAblock(blockNr) {
|
||||
if (blockNr >= blockCount) {
|
||||
sendLastOTA();
|
||||
return;
|
||||
}
|
||||
showProgress("Передан блок N: " + blockNr + " из " + blockCount + ", " + Math.floor(blockNr / (blockCount * 1.0) * 100) + "% успеха, время " + (new Date().getTime() - startTime) / 1000.0 + "сек");
|
||||
var blockNrString = getHexBLockCount(blockNr);
|
||||
var blockString = blockNrString + firmwareArray.substring(blockNr * 32, blockNr * 32 + 32);
|
||||
var blockCRC = getHexCRC(blockString);
|
||||
otaCharSend(blockString + blockCRC).then(function(character) {
|
||||
setTimeout(function() {
|
||||
if ((blockNr + 1) % 8 == 0) {
|
||||
otaCharacteristic.readValue().then(function(result) {
|
||||
console.log('Чтение OTA');
|
||||
sendOTAblock(blockNr + 1);
|
||||
}).catch(function(err) {
|
||||
updateFail(err);
|
||||
});
|
||||
} else {
|
||||
sendOTAblock(blockNr + 1);
|
||||
}
|
||||
}, 0);
|
||||
}).catch(function(err) {
|
||||
updateFail(err);
|
||||
});
|
||||
}
|
||||
|
||||
function getHexBLockCount(count) {
|
||||
var tempHEX = decimalToHex(count);
|
||||
return tempHEX.substring(2, 4) + tempHEX.substring(0, 2);
|
||||
}
|
||||
|
||||
|
||||
function sendLastOTA() {
|
||||
var data = "02ff" + getHexBLockCount(blockCount - 1) + getHexBLockCount(~(blockCount - 1) & 0xffff);
|
||||
otaCharSend(data).then(function(character) {
|
||||
showProgress("Прошивка выполнена за " + (new Date().getTime() - startTime) / 1000 + " сек");
|
||||
}).catch(function(err) {
|
||||
updateFail(err);
|
||||
});
|
||||
}
|
||||
|
||||
var otaCharSend = function(data) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
// console.log("OTA: " + data);
|
||||
otaCharacteristic.writeValue(hexToBytes(data)).then(function(character) {
|
||||
resolve("ok");
|
||||
}).catch(function(err) {
|
||||
reject("some error while sending char data");
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
var mainCharSend = function(data, characteristic) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
console.log("Send: " + data);
|
||||
characteristic.writeValue(hexToBytes(data)).then(function(character) {
|
||||
resolve("OK");
|
||||
}).catch(function(err) {
|
||||
reject("Some error while sending char data");
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function readAddr(addr) {
|
||||
if (myCharacteristic) {
|
||||
let blk = new Uint8Array([0xdb, addr&0xff, (addr>>8)&0xff, (addr>>16)&0xff, (addr>>24)&0xff]);
|
||||
myCharacteristic.writeValue(blk).then(_ => {
|
||||
startTime = new Date().getTime();
|
||||
showState("Прочитано 16 байт из адреса 0x" + hex(addr,8));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function writeAddr(addr, data) {
|
||||
if (myCharacteristic) {
|
||||
len = data.length;
|
||||
if(len != 0 && len <= 16) {
|
||||
let blk = new Uint8Array(len + 5);
|
||||
blk.set([0xdb, addr&0xff, (addr>>8)&0xff, (addr>>16)&0xff, (addr>>24)&0xff]);
|
||||
blk.set(data, 5);
|
||||
console.log(blk);
|
||||
myCharacteristic.writeValue(blk);
|
||||
showState("Записано " + len + " байт по адресу 0x" + hex(addr,8));
|
||||
} else {
|
||||
console.log(data);
|
||||
showState('Ошибка, длина блока от 1 до 16 байт!');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function infoReadAddr() {
|
||||
if(myCharacteristic) {
|
||||
let faddr = parseInt($('inputAddr').value, 16);
|
||||
readAddr(faddr);
|
||||
}
|
||||
}
|
||||
|
||||
function writeCmd(data) {
|
||||
if(myCharacteristic) {
|
||||
len = data.length;
|
||||
if(len != 0 && len <= 20) {
|
||||
let blk = new Uint8Array(data);
|
||||
console.log(blk);
|
||||
myCharacteristic.writeValue(blk);
|
||||
} else {
|
||||
console.log(data);
|
||||
showState('Ошибка, длина команды от 1 до 20 байт!');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function sendData() {
|
||||
let addr = parseInt($('inputAddr').value, 16);
|
||||
let data = hexToBytes($('inputData').value);
|
||||
if(data.length != 0 && data.length <= 16)
|
||||
writeAddr(addr, data);
|
||||
else
|
||||
console.log('Ошибка, длина от 1 до 16 байт!');
|
||||
|
||||
}
|
||||
|
||||
function sendCommand() {
|
||||
let data = hexToBytes($('inpCmdData').value);
|
||||
if(data.length != 0 && data.length <= 20)
|
||||
WriteCmd(data);
|
||||
else
|
||||
console.log('Должно быть от 1 до 20 hex байт!');
|
||||
}
|
||||
|
||||
|
||||
function customBlkParse(value) {
|
||||
let len = value.byteLength;
|
||||
if(len == 0) return;
|
||||
len--; // size from cmd
|
||||
let blkId = value.getUint8(0);
|
||||
s = 'Ответ на команду Id: ' + hex(blkId,2) + ' data: ' + bytesToHex(value.buffer.slice(1));
|
||||
addLog(s);
|
||||
if((blkId == 0xdb) && (value.byteLength > 4)) {
|
||||
len -= 4;
|
||||
let addr = value.getUint32(1,true);
|
||||
let s = bytesToHex(value.buffer.slice(5), len);
|
||||
$('inputData').value = s;
|
||||
addLog(hex(addr,8) + ':' + s);
|
||||
showProgress("Считано: " + len + " байт из 0x" + hex(addr,8));
|
||||
} else
|
||||
console.log('blk: ' + dump8(value, value.byteLength));
|
||||
}
|
||||
|
||||
var url;
|
||||
function download(data, filename, type) {
|
||||
var file = new Blob([data], {type: type});
|
||||
if (window.navigator.msSaveOrOpenBlob) { // ie10+
|
||||
window.navigator.msSaveOrOpenBlob(file, filename);
|
||||
} else { // ff, chrome
|
||||
url = URL.createObjectURL(file);
|
||||
let a = document.createElement("a");
|
||||
a.href = url;
|
||||
a.download = filename;
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
setTimeout(function(){document.body.removeChild(a);window.URL.revokeObjectURL(url);},0);
|
||||
URL.revokeObjectURL(url);
|
||||
}
|
||||
}
|
||||
|
||||
function readFile(file) {
|
||||
|
||||
var reader = new FileReader();
|
||||
|
||||
if (file != null) {
|
||||
reader.readAsArrayBuffer(file);
|
||||
} else {
|
||||
showError("Файл не загружен");
|
||||
}
|
||||
|
||||
reader.onload = function() {
|
||||
|
||||
// console.log(this.result);
|
||||
|
||||
firmwareArray = bytesToHex(this.result);
|
||||
if(firmwareArray.substring(0,4) != "1234"){
|
||||
blockCount = 0;
|
||||
firmwareArray = "";
|
||||
|
||||
$("lblFile").innerHTML = "не загружен";
|
||||
|
||||
alert("Выбранный файл не для PHY62x2 OTA!");
|
||||
showError("Выбранный файл не для PHY62x2 OTA!");
|
||||
|
||||
return;
|
||||
}
|
||||
showState("Файл загружен, размер: " + firmwareArray.length / 2 + " байт");
|
||||
|
||||
if (firmwareArray.length % 32 !== 0) { // pad last block to 16bytes
|
||||
var padHex = "ffffffffffffffffffffffffffffffff";
|
||||
firmwareArray += padHex.substr(0, 32 - firmwareArray.length % 32);
|
||||
}
|
||||
blockCount = firmwareArray.length / 32;
|
||||
addLog("Блоков: " + blockCount);
|
||||
}
|
||||
|
||||
reader.onerror = function() {
|
||||
console.log(this.error);
|
||||
};
|
||||
}
|
||||
|
||||
const selectFile = function() {
|
||||
|
||||
let regex = /[^\\]+$/
|
||||
|
||||
this.choose,
|
||||
this.selected
|
||||
|
||||
this.msg = str => {
|
||||
let prefix = '[selectFile]\n\nError: '
|
||||
return alert(prefix+str)
|
||||
}
|
||||
|
||||
this.check = () => {
|
||||
if (this.choose && this.selected != null) {
|
||||
let choose = document.getElementById(this.choose),
|
||||
selected = document.getElementById(this.selected)
|
||||
choose.addEventListener('change',() => {
|
||||
if (choose.value != '') {
|
||||
selected.innerHTML = choose.value.match(regex);
|
||||
readFile(choose.files[0]);
|
||||
}
|
||||
})
|
||||
} else {
|
||||
this.msg('Targets not set.')
|
||||
}
|
||||
}
|
||||
|
||||
selectFile.prototype.targets = (trigger, filetext) => {
|
||||
this.choose = trigger
|
||||
this.selected = filetext
|
||||
}
|
||||
|
||||
selectFile.prototype.simulate = () => {
|
||||
if (this.choose != null) {
|
||||
let choose = document.getElementById(this.choose)
|
||||
if (typeof choose != 'undefined') {
|
||||
choose.click()
|
||||
this.check()
|
||||
} else {
|
||||
this.msg('Could not find element '+this.choose)
|
||||
}
|
||||
} else {
|
||||
this.msg('Targets not set.')
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
var getFile = new selectFile;
|
||||
getFile.targets('inpFile','lblFile');
|
||||
|
||||
function openTab(evt, tabName) {
|
||||
var i, tabcontent, tablinks;
|
||||
tabcontent = document.getElementsByClassName("tabcontent");
|
||||
for (i = 0; i < tabcontent.length; i++) {
|
||||
tabcontent[i].style.display = "none";
|
||||
}
|
||||
tablinks = document.getElementsByClassName("tablinks");
|
||||
for (i = 0; i < tablinks.length; i++) {
|
||||
tablinks[i].className = tablinks[i].className.replace(" active", "");
|
||||
}
|
||||
document.getElementById(tabName).style.display = "block";
|
||||
evt.currentTarget.className += " active";
|
||||
console.log(evt.currentTarget.className);
|
||||
}
|
||||
|
||||
window.onload = function() {
|
||||
|
||||
$("btnSave").onclick = function() { download(flash_buf, 'ff.bin', 'application/octet-stream;charset=utf-8'); };
|
||||
}
|
||||
|
||||
|
||||
window.onload = (event) => {
|
||||
// console.log("page is fully loaded");
|
||||
showState("Нет подключения" )
|
||||
|
||||
openTab(event, 'tabOTA');
|
||||
// Selected Tab header style
|
||||
tablinks = document.getElementsByClassName("tablinks");
|
||||
tablinks[0].className += " active";
|
||||
};
|
||||
|
||||
</script>
|
||||
<h2>PHY62x2-BTHome <a href="https://github.com/pvvx/THB2"><small>ⓘ</small></a></h2>
|
||||
<label for="inpNamePrefix">Префикс названия устройств(а)</label><br>
|
||||
<input type="text" id="inpNamePrefix" value="" placeholder="THB, BT">
|
||||
<hr>
|
||||
<label id="lblStatus">Состояние: загрузка страницы</label>
|
||||
<br><br><hr>
|
||||
<button type="button" id="btnConnect" onclick="connect()">Соединение</button>
|
||||
<button type="button" id="btnDisconnect" onclick="disconnect()" disabled="true">Отключение</button>
|
||||
<button type="button" id="btnReconnect" onclick="reconnect()" disabled="true">Переподключение</button>
|
||||
<br><hr>
|
||||
<div class="tab">
|
||||
<button class="tablinks" onclick="openTab(event, 'tabOTA')">OTA</button>
|
||||
<button class="tablinks" onclick="openTab(event, 'tabFlash')">Flash</button>
|
||||
<button class="tablinks" onclick="openTab(event, 'tabService')">Service</button>
|
||||
</div>
|
||||
|
||||
<div id="tabOTA" class="tabcontent">
|
||||
<p>Файл прошивки:
|
||||
<input type=file hidden id=inpFile>
|
||||
<label id=lblFile>не выбран</label>
|
||||
<button type=button onClick=getFile.simulate()>Выбрать</button>
|
||||
<p>
|
||||
<hr>
|
||||
<button type="button"id="btnStartDFU" onclick="startDFU()" disabled="true" >Старт программирования</button>
|
||||
</div>
|
||||
|
||||
<div id="tabFlash" class="tabcontent">
|
||||
<p>
|
||||
<button type="button" id="btnReadFF" onclick="startReadFF()" disabled="true">Прочитать</button>
|
||||
<button type="button" id="btnSave" disabled="true">Сохранить в файл</button>
|
||||
<p>
|
||||
</div>
|
||||
|
||||
<div id="tabService" class="tabcontent">
|
||||
Чтение и запись памяти:<br>
|
||||
Адрес (hex): <input size="8" type="text" id="inputAddr" value="11000000" maxlength="8">
|
||||
<button type="button" id="btnReadAddr" onclick="infoReadAddr()" disabled="true">Прочитать</button>
|
||||
Данные (hex): <input size="32" type="text" id="inputData" value="?" maxlength="32">
|
||||
<button type="button" id="btnSendData" onclick="sendData()" disabled="true">Записать</button><hr>
|
||||
<button type="button" id="btnSendCommand" onclick="sendCommand()" disabled="true">Команда</button>
|
||||
<input type="text" id="inpCmdData" value="55" size="40" maxlength="40"><hr>
|
||||
</div>
|
||||
<hr>
|
||||
<button type="button" onclick="clearLog()">Очистить лог</button><br>
|
||||
<div id="log"></div>
|
||||
</body></html>
|
||||
40
bthome_phy6222/web/readme.txt
Normal file
40
bthome_phy6222/web/readme.txt
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
01ff 50485936 593601000000200100111001000020
|
||||
01ff 01000000 50485936 593601000000200100111001000020
|
||||
01ff 20010011 50485936 0100
|
||||
01ff 20010011 50485936 0010
|
||||
01ff 20010011 50485936 1200
|
||||
|
||||
ffffffff010000002000011110010000
|
||||
0000504859360100000020000111100100004388
|
||||
|
||||
Ñòàðò DFU
|
||||
OTA send: 00ff
|
||||
OTA read: ver: 01, err: 0, dbg: 0, start: 0, offs: 0x11010020, idx: 0x0010, total: 0x0011, crc: 0xC012FD5E
|
||||
OTA send: 01ff20000111504859361200
|
||||
OTA read: ver: 01, err: 0, dbg: 0, start: 1, offs: 0x11010020, idx: 0xFFFF, total: 0x0012, crc: 0xC012FD5E
|
||||
OTA send: 0000504859360100000020000111100100004388
|
||||
OTA read: ver: 01, err: 0, dbg: 0, start: 1, offs: 0x11010020, idx: 0x0000, total: 0x0012, crc: 0x557AB31D
|
||||
OTA send: 010020010000f00000002000011100000000440b
|
||||
OTA read: ver: 01, err: 0, dbg: 0, start: 1, offs: 0x11010020, idx: 0x0001, total: 0x0012, crc: 0xD52EEB28
|
||||
OTA send: 020000000000000000000000000000000000d05c
|
||||
OTA read: ver: 01, err: 0, dbg: 0, start: 1, offs: 0x11010020, idx: 0x0002, total: 0x0012, crc: 0x04517BB9
|
||||
OTA send: 03000000000000000000000000000000000081a0
|
||||
OTA read: ver: 01, err: 0, dbg: 0, start: 1, offs: 0x11010020, idx: 0x0003, total: 0x0012, crc: 0xD28B9AE6
|
||||
OTA send: 04000000000000000000000000000000000030d5
|
||||
OTA read: ver: 01, err: 0, dbg: 0, start: 1, offs: 0x11010020, idx: 0x0004, total: 0x0012, crc: 0x5E306857
|
||||
OTA send: 0500000000000000000000000000000000006129
|
||||
OTA read: ver: 01, err: 0, dbg: 0, start: 1, offs: 0x11010020, idx: 0x0005, total: 0x0012, crc: 0xE0ADC600
|
||||
OTA send: 060000000000000000000000000000000000916d
|
||||
OTA read: ver: 01, err: 0, dbg: 0, start: 1, offs: 0x11010020, idx: 0x0006, total: 0x0012, crc: 0xF1F2471C
|
||||
|
||||
29:29: Ïîèñê óñòðîéñòâ
|
||||
29:31: Connecting to: BTH01-31BDBC
|
||||
29:31: OTA: FF010100200001111100120050485936E5394CC0
|
||||
29:31: DevCfg: 000000001F501D000206B400
|
||||
29:31: Óñòðîéñòâî ïîäêëþ÷åíî.
|
||||
29:33: Ôàéë:
|
||||
29:33: PHY6 OTA ID: 36594850, Ñåãìåíòîâ: 1, Ñòàðò: 0x11010000, Ðàçìåð: 20304 áàéò
|
||||
29:33: Ðàçìåð ôàéëà: 20308 áàéò
|
||||
29:33: Ñ÷åò÷èê: 1270
|
||||
29:46: Ñòàðò ïðîãðàììèðîâàíèÿ...
|
||||
31:56: Ïðîãðàììèðîâàíèå çàâåðøåíî çà 129.404 ñåêóíä
|
||||
BIN
bthome_phy6222/web/test2.bin
Normal file
BIN
bthome_phy6222/web/test2.bin
Normal file
Binary file not shown.
Loading…
Add table
Add a link
Reference in a new issue