This commit is contained in:
pvvx 2024-02-06 03:06:37 +03:00
parent c63b2b1c9a
commit 24ec79d420
39 changed files with 16062 additions and 6228 deletions

View file

@ -3,11 +3,11 @@ Custom firmware for Tuya [THB2](https://pvvx.github.io/THB2), [BTH01](https://pv
* Тестовый [PHY62x2BTHome.html](https://pvvx.github.io/THB2/web/PHY62x2BTHome.html)
Прошивка Boot-OTA для THB2 (файл bin\BOOT_THB2_v1x.hex).
Прошивка Boot-OTA для THB2 (файл bin\BOOT_THB2_v10.hex).
Прошивка Boot-OTA для BTH01 (файл bin\BOOT_BTH01_v1x.hex).
Прошивка Boot-OTA для BTH01 (файл bin\BOOT_BTH01_v10.hex).
Прошивка Boot-OTA для TH05 (файл bin\BOOT_TH05_v1x.hex).
Прошивка Boot-OTA для TH05 (файл bin\BOOT_TH05_v10.hex).
## Основные характеристики:
@ -22,6 +22,14 @@ Custom firmware for Tuya [THB2](https://pvvx.github.io/THB2), [BTH01](https://pv
* Интервал соединения с учетом Connect Latency - 900 мс
* Поддерживаемые сенсоры температуры и влажности: AHT30, CHT8305, CHT8215, CHT8310
## История версий:
| N | Описание |
|---|--- |
| 1.0 | Первая релизная версия |
| 1.1 | Добавлен триггер - вывод TX2 срабатывающий по установленным значениям температуры и/или влажности с гистерезисами. Передача состояния вывода RX2. Для термометров с экраном добавлен показ смайлика с "комфортом". |
## Прошивка:
Прошить устройство програмой Boot-OTA возможно через USB-COM адаптер с выходами на 3.3В:

BIN
bin/BTH01_v11.bin Normal file

Binary file not shown.

BIN
bin/TH05_v11.bin Normal file

Binary file not shown.

BIN
bin/THB2_v11.bin Normal file

Binary file not shown.

View file

@ -14,6 +14,7 @@ SRC_PRJ += osal_peripheral.c
SRC_PRJ += peripheral_main.c
SRC_PRJ += sbp_profile.c
SRC_PRJ += devinfoservice.c
SRC_PRJ += trigger.c
SRC_PRJ += sensors.c
SRC_PRJ += dev_i2c.c
SRC_PRJ += config.c

View file

@ -19,6 +19,7 @@
#include "log.h"
#include "global_config.h"
#define TEST_PIN_NUM 0
extern uint32_t s_gpio_wakeup_src_group1,s_gpio_wakeup_src_group2;
@ -128,9 +129,10 @@ static int hal_gpio_interrupt_disable(gpio_pin_e pin)
void hal_gpio_write(gpio_pin_e pin, uint8_t en)
{
// hal_gpio_pin_init(pin,GPIO_OUTPUT);
#if TEST_PIN_NUM
if (pin > (NUMBER_OF_PINS - 1))
return;
#endif
if(en)
AP_GPIO->swporta_dr |= BIT(pin);
@ -142,8 +144,10 @@ void hal_gpio_write(gpio_pin_e pin, uint8_t en)
void hal_gpio_fast_write(gpio_pin_e pin, uint8_t en)
{
#if TEST_PIN_NUM
if (pin > (NUMBER_OF_PINS - 1))
return;
#endif
if(en)
AP_GPIO->swporta_dr |= BIT(pin);
@ -154,9 +158,10 @@ void hal_gpio_fast_write(gpio_pin_e pin, uint8_t en)
bool hal_gpio_read(gpio_pin_e pin)
{
uint32_t r;
#if TEST_PIN_NUM
if (pin > (NUMBER_OF_PINS - 1))
return PPlus_ERR_NOT_SUPPORTED;
#endif
if(AP_GPIO->swporta_ddr & BIT(pin))
r = AP_GPIO->swporta_dr;
@ -168,9 +173,10 @@ bool hal_gpio_read(gpio_pin_e pin)
void hal_gpio_fmux(gpio_pin_e pin, bit_action_e value)
{
#if TEST_PIN_NUM
if (pin > (NUMBER_OF_PINS - 1))
return;
#endif
if(value)
{
// if((pin == P2) || (pin == P3))
@ -201,9 +207,10 @@ void hal_gpio_fmux_set(gpio_pin_e pin, gpio_fmux_e type)
int hal_gpio_pin_init(gpio_pin_e pin, gpio_dir_t type)
{
#if TEST_PIN_NUM
if (pin > (NUMBER_OF_PINS - 1))
return PPlus_ERR_NOT_SUPPORTED;
#endif
// if((m_gpioCtx.pin_assignments[pin] == GPIO_PIN_ASSI_OUT) &&
// (m_gpioCtx.pin_retention_status & BIT(pin)) && (type == GPIO_INPUT))
// return PPlus_ERR_INVALID_PARAM;
@ -250,8 +257,10 @@ static void hal_gpio_wakeup_control(gpio_pin_e pin, bit_action_e value)
void hal_gpio_ds_control(gpio_pin_e pin, bit_action_e value)
{
#if TEST_PIN_NUM
if (pin > (NUMBER_OF_PINS - 1))
return;
#endif
if(value)
AP_IOMUX->pad_ps0 |= BIT(pin);
@ -261,8 +270,10 @@ void hal_gpio_ds_control(gpio_pin_e pin, bit_action_e value)
int hal_gpioretention_unregister(gpio_pin_e pin)
{
if (pin > (NUMBER_OF_PINS - 1))
#if TEST_PIN_NUM
if (pin > (NUMBER_OF_PINS - 1))
return PPlus_ERR_NOT_SUPPORTED;
#endif
if(m_gpioCtx.pin_assignments[pin] != GPIO_PIN_ASSI_OUT)
return PPlus_ERR_INVALID_PARAM;
@ -275,9 +286,10 @@ int hal_gpioretention_unregister(gpio_pin_e pin)
int hal_gpioin_unregister(gpio_pin_e pin)
{
gpioin_Ctx_t* p_irq_ctx = &(m_gpioCtx.irq_ctx[0]);
#if TEST_PIN_NUM
if (pin > (NUMBER_OF_PINS - 1))
return PPlus_ERR_NOT_SUPPORTED;
#endif
hal_gpioin_disable(pin);
p_irq_ctx[pin].negedgeHdl = NULL;
@ -290,8 +302,10 @@ int hal_gpio_cfg_analog_io(gpio_pin_e pin, bit_action_e value)
if((pin < P11) || (pin > P25))
return PPlus_ERR_INVALID_PARAM;
#if TEST_PIN_NUM
if (pin > (NUMBER_OF_PINS - 1))
return PPlus_ERR_NOT_SUPPORTED;
#endif
if(value)
{
@ -309,8 +323,10 @@ int hal_gpio_cfg_analog_io(gpio_pin_e pin, bit_action_e value)
void hal_gpio_pull_set(gpio_pin_e pin, gpio_pupd_e type)
{
#if TEST_PIN_NUM
if (pin > (NUMBER_OF_PINS - 1))
return;
#endif
uint8_t i = c_gpio_pull[pin].reg_i;
uint8_t h = c_gpio_pull[pin].bit_h;
@ -324,9 +340,10 @@ void hal_gpio_pull_set(gpio_pin_e pin, gpio_pupd_e type)
void hal_gpio_wakeup_set(gpio_pin_e pin, gpio_polarity_e type)
{
#if TEST_PIN_NUM
if (pin > (NUMBER_OF_PINS - 1))
return;
#endif
uint8_t i = c_gpio_pull[pin].reg_i;
uint8_t p = c_gpio_pull[pin].bit_l-1;
@ -364,8 +381,10 @@ void hal_gpio_pin2pin3_control(gpio_pin_e pin, uint8_t en)//0:sw,1:other func
#if(CFG_SLEEP_MODE == PWR_MODE_SLEEP)
static void hal_gpio_retention_enable(gpio_pin_e pin,uint8_t en)
{
#if TEST_PIN_NUM
if (pin > (NUMBER_OF_PINS - 1))
return;
#endif
if(en)
{
@ -396,8 +415,10 @@ int hal_gpioin_disable(gpio_pin_e pin)
{
gpioin_Ctx_t* p_irq_ctx = &(m_gpioCtx.irq_ctx[0]);
#if TEST_PIN_NUM
if (pin > (NUMBER_OF_PINS - 1))
return PPlus_ERR_NOT_SUPPORTED;
#endif
p_irq_ctx[pin].enable = FALSE;
m_gpioCtx.pin_assignments[pin] = GPIO_PIN_ASSI_NONE;
@ -409,8 +430,10 @@ static int hal_gpio_interrupt_enable(gpio_pin_e pin, gpio_polarity_e type)
{
uint32_t gpio_tmp;
#if TEST_PIN_NUM
if (pin > (NUMBER_OF_PINS - 1))
return PPlus_ERR_NOT_SUPPORTED;
#endif
gpio_tmp = AP_GPIO->inttype_level;
gpio_tmp |= (1 << pin); //edge sensitive
@ -436,8 +459,10 @@ static void hal_gpioin_event_pin(gpio_pin_e pin, gpio_polarity_e type)
{
gpioin_Ctx_t* p_irq_ctx = &(m_gpioCtx.irq_ctx[0]);
#if TEST_PIN_NUM
if (pin > (NUMBER_OF_PINS - 1))
return;
#endif
if (p_irq_ctx[pin].posedgeHdl && (type == POL_RISING ))
{
@ -452,8 +477,10 @@ static void hal_gpioin_event_pin(gpio_pin_e pin, gpio_polarity_e type)
#if(CFG_SLEEP_MODE == PWR_MODE_SLEEP)
static void hal_gpioin_wakeup_trigger(gpio_pin_e pin)
{
#if TEST_PIN_NUM
if (pin > (NUMBER_OF_PINS - 1))
return;
#endif
uint8_t pin_state = (uint8_t)hal_gpio_read(pin);
gpio_polarity_e type = pin_state ? POL_RISING : POL_FALLING;
@ -597,8 +624,10 @@ int hal_gpioin_enable(gpio_pin_e pin)
gpio_polarity_e type = POL_FALLING;
uint32 pinVal = 0;
#if TEST_PIN_NUM
if (pin > (NUMBER_OF_PINS - 1))
return PPlus_ERR_NOT_SUPPORTED;
#endif
if (p_irq_ctx[pin].posedgeHdl == NULL && p_irq_ctx[pin].negedgeHdl == NULL)
return PPlus_ERR_NOT_REGISTED;
@ -628,8 +657,10 @@ int hal_gpioin_enable(gpio_pin_e pin)
int hal_gpioretention_register(gpio_pin_e pin)
{
#if TEST_PIN_NUM
if (pin > (NUMBER_OF_PINS - 1))
return PPlus_ERR_NOT_SUPPORTED;
#endif
hal_gpio_pin_init(pin, GPIO_OUTPUT);
m_gpioCtx.pin_assignments[pin] = GPIO_PIN_ASSI_OUT;

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

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.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -1,5 +1,5 @@
@set PATH=D:\MCU\GNU_Tools_ARM_Embedded\13.2.rel1\bin;%PATH%
@set SWVER=_v10
@set SWVER=_v11
@del /Q "build\THB2%SWVER%.hex"
@del /Q "build\THB2%SWVER%.bin"
@mkdir .\bin

View file

@ -9,7 +9,7 @@
#include "thb2_main.h"
#include "pwrmgr.h"
#include "jump_function.h"
#include "sensors.h"
#include "sensor.h"
#ifndef ADC_PIN
#define ADC_PIN GPIO_P11

View file

@ -17,7 +17,7 @@
#include "peripheral.h"
#include "battservice.h"
#include "sensors.h"
#include "sensor.h"
/*********************************************************************
MACROS
*/

View file

@ -9,7 +9,7 @@
#include "config.h"
#include "bcomdef.h"
#include "gapbondmgr.h"
#include "sensors.h"
#include "sensor.h"
#include "bthome_beacon.h"
uint8_t bthome_data_beacon(void * padbuf) {

View file

@ -21,7 +21,7 @@
#include "flash_eep.h"
#include "bleperipheral.h"
#include "sbp_profile.h"
#include "sensors.h"
#include "sensor.h"
#include "cmd_parcer.h"
#include "devinfoservice.h"
#include "ble_ota.h"

View file

@ -21,13 +21,14 @@
#include "flash_eep.h"
#include "thb2_main.h"
#include "sbp_profile.h"
#include "sensors.h"
#include "sensor.h"
#include "cmd_parser.h"
#include "devinfoservice.h"
#include "ble_ota.h"
#include "thb2_peripheral.h"
#include "lcd_th05.h"
#include "logger.h"
#include "trigger.h"
/*********************************************************************/
extern gapPeriConnectParams_t periConnParameters;
@ -86,6 +87,18 @@ int cmd_parser(uint8_t * obuf, uint8_t * ibuf, uint32_t len) {
} else if (cmd == CMD_ID_SEN_ID) {
memcpy(&obuf[1], (uint8_t *)&thsensor_cfg.mid, 5);
olen = 1 + 5;
#if (OTA_TYPE == OTA_TYPE_APP) && ((DEV_SERVICES & SERVICE_TH_TRG) || (DEV_SERVICES & SERVICE_SCREEN))
} else if (cmd == CMD_ID_TRG) { // Get/Set tigger data config
if (--len > trigger_send_size)
len = trigger_send_size;
if (len) {
memcpy(&trg, &ibuf[1], len);
flash_write_cfg(&trg, EEP_ID_TRG, trigger_send_size);
}
memcpy(&obuf[1], &trg, trigger_send_size);
olen = trigger_send_size + 1;
#endif
#endif
#if (DEV_SERVICES & SERVICE_HISTORY)
} else if (cmd == CMD_ID_LOGGER && len > 2) { // Read memory measures

View file

@ -39,7 +39,7 @@ typedef enum {
CMD_ID_LOGGER = 0x35, // Read memory measures
CMD_ID_CLRLOG = 0x36, // Clear memory measures
CMD_ID_RDS = 0x40, // Get/Set Reed switch config (DIY devices)
CMD_ID_TRG = 0x44, // Get/Set trg and Reed switch data config
CMD_ID_TRG = 0x44, // Get/Set tigger data config
CMD_ID_TRG_OUT = 0x45, // Get/Set trg out, Send Reed switch and trg data
CMD_ID_HXC = 0x49, // Get/Set HX71X config
CMD_ID_CFG = 0x55, // Get/Set device config

View file

@ -34,10 +34,11 @@
#include "thservice.h"
#include "thb2_peripheral.h"
#include "bthome_beacon.h"
#include "sensors.h"
#include "sensor.h"
#include "battery.h"
#include "sbp_profile.h"
#include "logger.h"
#include "trigger.h"
extern gapPeriConnectParams_t periConnParameters;
@ -91,7 +92,7 @@ void test_config(void) {
if (cfg.rf_tx_power > RF_PHY_TX_POWER_EXTRA_MAX)
cfg.rf_tx_power = RF_PHY_TX_POWER_EXTRA_MAX;
g_rfPhyTxPower = cfg.rf_tx_power;
//rf_phy_set_txPower(g_rfPhyTxPower);
rf_phy_set_txPower(g_rfPhyTxPower);
gapRole_MinConnInterval = periConnParameters.intervalMin = DEFAULT_DESIRED_MIN_CONN_INTERVAL;
gapRole_MaxConnInterval = periConnParameters.intervalMax = DEFAULT_DESIRED_MAX_CONN_INTERVAL;
@ -112,7 +113,12 @@ void test_config(void) {
void load_eep_config(void) {
if(!flash_supported_eep_ver(0, APP_VERSION)) {
memcpy(&cfg, &def_cfg, sizeof(cfg));
#if (DEV_SERVICES & SERVICE_THS)
memset(&thsensor_cfg.coef, 0, sizeof(thsensor_cfg.coef));
#endif
#if (OTA_TYPE == OTA_TYPE_APP) && ((DEV_SERVICES & SERVICE_TH_TRG) || (DEV_SERVICES & SERVICE_SCREEN))
memcpy(&trg, &def_trg, sizeof(trg));
#endif
} else {
if (flash_read_cfg(&cfg, EEP_ID_CFG, sizeof(cfg)) != sizeof(cfg))
memcpy(&cfg, &def_cfg, sizeof(cfg));
@ -121,12 +127,17 @@ void load_eep_config(void) {
memset(&thsensor_cfg.coef, 0, sizeof(thsensor_cfg.coef));
}
#endif
}
#if (DEV_SERVICES & SERVICE_TIME_ADJUST)
if (flash_read_cfg(&clkt.delta_time, EEP_ID_TIM, sizeof(&clkt.delta_time)) != sizeof(&clkt.delta_time)) {
clkt.delta_time = 0;
}
#if (OTA_TYPE == OTA_TYPE_APP) && ((DEV_SERVICES & SERVICE_TH_TRG) || (DEV_SERVICES & SERVICE_SCREEN))
if (flash_read_cfg(&trg, EEP_ID_TRG, trigger_send_size) != trigger_send_size) {
memcpy(&trg, &def_trg, sizeof(trg));
}
#endif
#if (DEV_SERVICES & SERVICE_TIME_ADJUST)
if (flash_read_cfg(&clkt.delta_time, EEP_ID_TIM, sizeof(&clkt.delta_time)) != sizeof(&clkt.delta_time)) {
clkt.delta_time = 0;
}
#endif
}
#if (DEV_SERVICES & SERVICE_HISTORY)
memo_init();
#endif

View file

@ -1,7 +1,7 @@
/*
* config.h
*
* Created on: 11 янв. 2024 г.
* Created on: 11/01/2024
* Author: pvvx
*/
@ -13,7 +13,7 @@
// #include "bus_dev.h"
#ifndef APP_VERSION
#define APP_VERSION 0x10 // BCD
#define APP_VERSION 0x11 // BCD
#endif
/*
@ -52,19 +52,20 @@
#define SERVICE_SCREEN 0x00000020 // есть экран
#define SERVICE_LE_LR 0x00000040 // пока нет: Есть поддержка рекламы в LE Long Range
#define SERVICE_THS 0x00000080 // есть датчик температуры и влажности
#define SERVICE_RDS 0x00000100 // пока нет есть обслуживние геркона/счета импульсов
#define SERVICE_RDS 0x00000100 // пока нет: есть обслуживние геркона/счета импульсов
#define SERVICE_KEY 0x00000200 // есть кнопка
#define SERVICE_OUTS 0x00000400 // пока нет: есть обслуживние выходных пинов
#define SERVICE_INS 0x00000800 // пока нет: есть обслуживние входных пинов
#define SERVICE_TIME_ADJUST 0x00001000 // пока нет: есть функция коррекции счета времени
#define SERVICE_HARD_CLOCK 0x00002000 // пока нет: есть реальные часы RTC
#define SERVICE_TH_TRG 0x00004000 // триггер по температуре и влажности
#define OTA_TYPE_NONE 0 // нет OTA, только переключение из APP на boot прошивку
#define OTA_TYPE_BOOT SERVICE_OTA // вариант для прошивки boot + OTA
#define OTA_TYPE_APP OTA_TYPE_NONE
#ifndef OTA_TYPE
#define OTA_TYPE OTA_TYPE_BOOT
#define OTA_TYPE OTA_TYPE_APP
#endif
#if OTA_TYPE == OTA_TYPE_BOOT
@ -85,6 +86,7 @@
| SERVICE_THS \
| SERVICE_KEY \
| SERVICE_HISTORY \
| SERVICE_TH_TRG \
)
#endif
@ -99,6 +101,9 @@
#define LED_ON 0
#define LED_OFF 1
#define GPIO_TRG GPIO_P09 // TX
#define GPIO_INP GPIO_P10 // RX
#define DEF_MODEL_NUMBER_STR "THB2"
#define DEF_HARDWARE_REVISION "0001"
#define DEF_MANUFACTURE_NAME_STR "Tuya"
@ -115,6 +120,7 @@
| SERVICE_THS \
| SERVICE_KEY \
| SERVICE_HISTORY \
| SERVICE_TH_TRG \
)
#endif
@ -130,6 +136,9 @@
#define LED_ON 1
#define LED_OFF 0
#define GPIO_TRG GPIO_P20 // mark TX2
#define GPIO_INP GPIO_P18 // mark RX2
#define DEF_MODEL_NUMBER_STR "BTH01"
#define DEF_HARDWARE_REVISION "0001"
#define DEF_MANUFACTURE_NAME_STR "Tuya"
@ -148,9 +157,14 @@
| SERVICE_THS \
| SERVICE_KEY \
| SERVICE_HISTORY \
| SERVICE_TH_TRG \
)
#endif
#if ((DEV_SERVICES & SERVICE_THS) == 0) && (DEV_SERVICES & SERVICE_TH_TRG)
#error "Not SERVICE_TH_TRG!"
#endif
#define ADC_PIN_USE_OUT 1 // hal_gpio_write(ADC_PIN, 1);
#define ADC_PIN GPIO_P11
#define ADC_CHL ADC_CH1N_P11
@ -163,8 +177,11 @@
#define I2C_SCL GPIO_P34 // AHT20_SCL
#define GPIO_SPWR GPIO_P00 // питание сенсора CHT8305_VDD
#define GPIO_KEY GPIO_P14
#define GPIO_LPWR GPIO_P02 // питание LCD драйвера
#define GPIO_TRG GPIO_P20 // mark TX2
#define GPIO_INP GPIO_P18 // mark RX2
//#define GPIO_LED GPIO_P20
//#define LED_ON 1
//#define LED_OFF 0
@ -205,7 +222,9 @@ extern const cfg_t def_cfg;
#define FLG_MEAS_NOTIFY 0x00000001 // включить Notify измерений
#define FLG_SHOW_TIME 0x00000002 // включить показ часов на LCD
#define FLG_ADV_CRYPT 0x00000004 // Зашифрованная BLE реклама (bindkey)
#define FLG_SHOW_SMILEY 0x00000004 // включить показ смайлика
#define FLG_SHOW_TRG 0x00000008 // смайлик поаказывает TRG
#define FLG_ADV_CRYPT 0x00000010 // Зашифрованная BLE реклама (bindkey)
typedef struct _adv_work_t {
uint32_t measure_interval_ms;

View file

@ -16,7 +16,7 @@ extern "C" {
#define EEP_ID_MAC (0xACAD) // EEP ID MAC
#define EEP_ID_CFG (0x0CFC) // EEP ID config data
#define EEP_ID_CFS (0x0CF5) // EEP ID sensor coefficients
//#define EEP_ID_RPC (0x0DF5) // EEP ID reed switch pulse counter
#define EEP_ID_TRG (0x1DF5) // EEP ID TH trigger config
//#define EEP_ID_PCD (0xC0DE) // EEP ID pincode
//#define EEP_ID_CMF (0x0FCC) // EEP ID comfort data
#define EEP_ID_DVN (0xDEAE) // EEP ID device name

View file

@ -12,7 +12,7 @@
#include "gpio.h"
#include "rom_sym_def.h"
#include "dev_i2c.h"
#include "sensors.h"
#include "sensor.h"
#include "lcd_th05.h"
#include "thb2_peripheral.h"
@ -107,7 +107,7 @@ const uint8_t lcd_init_cmd[] = {
* 0x5 = "°F"
* 0x6 = " ="
* 0x7 = "°E" */
void show_temp_symbol(CLD_TEMP_SYMBOL symbol) {
void show_temp_symbol(LCD_TEMP_SYMBOLS symbol) {
display_buff[2] &= ~BIT(3);
display_buff[3] &= ~(BIT(7)|BIT(5)) ;
display_buff[2] |= (symbol << 2) & BIT(3);
@ -122,10 +122,10 @@ void show_temp_symbol(CLD_TEMP_SYMBOL symbol) {
* 5 = "(^_^)" happy
* 6 = "(-^-)" sad
* 7 = "(ooo)" */
void show_smiley(uint8_t state) {
void show_smiley(LCD_SMILEY_SYMBOLS symbol) {
display_buff[3] &= ~0x15;
state = (state & 1) | ((state << 1) & 4) | ((state << 2) & 0x10);
display_buff[3] |= state;
symbol = (symbol & 1) | ((symbol << 1) & 4) | ((symbol << 2) & 0x10);
display_buff[3] |= symbol;
}
void show_ble_symbol(bool state) {
@ -234,13 +234,44 @@ 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(CLD_TSYMBOL_C);
show_temp_symbol(LCD_TSYMBOL_C);
#if (OTA_TYPE == OTA_TYPE_APP)
if(cfg.flg & FLG_SHOW_SMILEY) {
#if (DEV_SERVICES & SERVICE_TH_TRG)
if(cfg.flg & FLG_SHOW_TRG) {
if(measured_data.flg.comfort) {
if(measured_data.flg.trg_on)
show_smiley(LD_SSYMBOL_HAPPY);
else
show_smiley(LD_SSYMBOL__HAPPY);
} else {
if(measured_data.flg.trg_on)
show_smiley(LD_SSYMBOL_SAD);
else
show_smiley(LD_SSYMBOL__SAD);
}
} else
#endif // SERVICE_TH_TRG
if(measured_data.flg.comfort)
show_smiley(LD_SSYMBOL_HAPPY);
else
show_smiley(LD_SSYMBOL_SAD);
#if (DEV_SERVICES & SERVICE_TH_TRG)
} else if(cfg.flg & FLG_SHOW_TRG) {
if(measured_data.flg.trg_on)
show_smiley(LD_SSYMBOL_CC);
else
show_smiley(LD_SSYMBOL_OFF);
} else
#endif // SERVICE_TH_TRG
#endif // OTA_TYPE
show_smiley(LD_SSYMBOL_OFF);
#else
show_big_number_x10(measured_data.battery_mv/100);
show_small_number((measured_data.battery > 99)? 99 : measured_data.battery, true);
show_battery_symbol(1);
#endif
show_smiley(0);
show_smiley(LD_SSYMBOL_OFF);
#endif // SERVICE_THS
show_ble_symbol(gapRole_state == GAPROLE_CONNECTED);
update_lcd();
}

View file

@ -49,12 +49,31 @@ extern uint8_t display_buff[LCD_BUF_SIZE];
* 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;
LCD_TSYMBOL_NONE, // " "
LCD_TSYMBOL_C = 3, // "°C"
LCD_TSYMBOL_F = 5, // "°F"
LCD_TSYMBOL_EQ = 6, // " ="
LCD_TSYMBOL_E = 7 // "°E"
} LCD_TEMP_SYMBOLS;
/* 0 = " " off,
* 1 = " ^_^ " happy
* 2 = " -^- " sad
* 3 = " ooo "
* 4 = "( )"
* 5 = "(^_^)" happy
* 6 = "(-^-)" sad
* 7 = "(ooo)" */
typedef enum {
LD_SSYMBOL_OFF, // 0 = " " off,
LD_SSYMBOL__HAPPY, // 1 = " ^_^ " happy
LD_SSYMBOL__SAD, // 2 = " -^- " sad
LD_SSYMBOL_OOO, // 3 = " ooo "
LD_SSYMBOL_CC, // 4 = "( )"
LD_SSYMBOL_HAPPY, // 5 = "(^_^)" happy
LD_SSYMBOL_SAD, // 6 = "(-^-)" sad
LD_SSYMBOL_ALL, // 7 = "(ooo)"
} LCD_SMILEY_SYMBOLS;
void init_lcd(void);
void update_lcd(void);
@ -62,8 +81,8 @@ void show_small_number(int16_t number, bool percent);
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(CLD_TEMP_SYMBOL symbol);
void show_smiley(LCD_SMILEY_SYMBOLS symbol);
void show_temp_symbol(LCD_TEMP_SYMBOLS symbol);
//void chow_clock(void);
//void chow_measure(void);

View file

@ -9,7 +9,7 @@
#include "flash.h"
#include "flash_eep.h"
#include "logger.h"
#include "sensors.h"
#include "sensor.h"
#include "cmd_parser.h"
#define RAM

View file

@ -27,7 +27,7 @@
#include "logger.h"
#include "hci.h"
#include "lcd_th05.h"
#include "sensors.h"
#include "sensor.h"
/*********************************************************************
* MACROS

View file

@ -0,0 +1,198 @@
/*
sensor.h
Author: pvvx
*/
#ifndef _SENSORS_H_
#define _SENSORS_H_
#include "config.h"
#if (DEV_SERVICES & SERVICE_THS)
// Timing
#define SENSOR_POWER_TIMEOUT_ms 3
#define SENSOR_RESET_TIMEOUT_ms 3
#define SENSOR_MEASURING_TIMEOUT_ms 7
#define CHT83xx_I2C_ADDR 0x40
#define CHT83xx_REG_TMP 0x00
#define CHT83xx_REG_HMD 0x01
#define CHT83xx_REG_MID 0xfe
#define CHT83xx_REG_VID 0xff
#define CHT83xx_MID 0x5959
/* CHT8310 https://github.com/pvvx/pvvx.github.io/blob/master/THB2/CHT8310.Advanced.Datasheet_Ver1.0.20230407.pdf */
// I2C addres
#define CHT8215_I2C_ADDR0 0x40
#define CHT8215_I2C_ADDR1 0x44
#define CHT8215_I2C_ADDR2 0x48
#define CHT8215_I2C_ADDR3 0x4C
// Registers
#define CHT8215_REG_TMP 0x00
#define CHT8215_REG_HMD 0x01
#define CHT8215_REG_STA 0x02
#define CHT8215_REG_CFG 0x03
#define CHT8215_REG_CRT 0x04
#define CHT8215_REG_TLL 0x05
#define CHT8215_REG_TLM 0x06
#define CHT8215_REG_HLL 0x07
#define CHT8215_REG_HLM 0x08
#define CHT8215_REG_OST 0x0f
#define CHT8215_REG_RST 0xfc
#define CHT8215_REG_MID 0xfe
#define CHT8215_REG_VID 0xff
// Status register mask
#define CHT8215_STA_BUSY 0x8000
#define CHT8215_STA_THI 0x4000
#define CHT8215_STA_TLO 0x2000
#define CHT8215_STA_HHI 0x1000
#define CHT8215_STA_HLO 0x0800
// Config register mask
#define CHT8215_CFG_MASK 0x8000
#define CHT8215_CFG_SD 0x4000
#define CHT8215_CFG_ALTH 0x2000
#define CHT8215_CFG_EM 0x1000
#define CHT8215_CFG_EHT 0x0100
#define CHT8215_CFG_TME 0x0080
#define CHT8215_CFG_POL 0x0020
#define CHT8215_CFG_ALT 0x0018
#define CHT8215_CFG_CONSEC_FQ 0x0006
#define CHT8215_CFG_ATM 0x0001
#define CHT8315_MID 0x5959
#define CHT8215_VID 0x1582
/* CHT8305 https://github.com/pvvx/pvvx.github.io/blob/master/BTH01/CHT8305.pdf */
// I2C addres
#define CHT8305_I2C_ADDR0 0x40
#define CHT8305_I2C_ADDR1 0x41
#define CHT8305_I2C_ADDR2 0x42
#define CHT8305_I2C_ADDR3 0x43
#define CHT8305_I2C_ADDR_MAX 0x43
// Registers
#define CHT8305_REG_TMP 0x00
#define CHT8305_REG_HMD 0x01
#define CHT8305_REG_CFG 0x02
#define CHT8305_REG_ALR 0x03
#define CHT8305_REG_VLT 0x04
#define CHT8305_REG_MID 0xfe
#define CHT8305_REG_VID 0xff
// Config register mask
#define CHT8305_CFG_SOFT_RESET 0x8000
#define CHT8305_CFG_CLOCK_STRETCH 0x4000
#define CHT8305_CFG_HEATER 0x2000
#define CHT8305_CFG_MODE 0x1000
#define CHT8305_CFG_VCCS 0x0800
#define CHT8305_CFG_TEMP_RES 0x0400
#define CHT8305_CFG_HUMI_RES 0x0300
#define CHT8305_CFG_ALERT_MODE 0x00C0
#define CHT8305_CFG_ALERT_PENDING 0x0020
#define CHT8305_CFG_ALERT_HUMI 0x0010
#define CHT8305_CFG_ALERT_TEMP 0x0008
#define CHT8305_CFG_VCC_ENABLE 0x0004
#define CHT8305_CFG_RESERVED 0x0003
/*
struct __attribute__((packed)) _cht8305_config_t{
uint16_t reserved : 2;
uint16_t vccen : 1;
uint16_t talt : 1;
uint16_t halt : 1;
uint16_t aps : 1;
uint16_t altm : 2;
uint16_t h_res : 2;
uint16_t t_res : 1;
uint16_t vccs : 1;
uint16_t mode : 1;
uint16_t heater : 1;
uint16_t clkstr : 1;
uint16_t srst : 1;
} cht8305_config_t;
*/
#define CHT8305_MID 0x5959
#define CHT8305_VID 0x0583
/*---------------------------------------
Датчик влажности AHT25
---------------------------------------*/
#define AHT2x_I2C_ADDR 0x38
#define AHT2x_CMD_INI 0x0E1 // Initialization Command
#define AHT2x_CMD_TMS 0x0AC // Trigger Measurement Command
#define AHT2x_DATA_TMS 0x3300 // Trigger Measurement data
#define AHT2x_CMD_RST 0x0BA // Soft Reset Command
typedef struct __attribute__((packed)) _measured_flg_t {
uint8_t pin_input : 1; // GPIO_INP input pin
uint8_t trg_output : 1; // GPIO_TRG pin output value
uint8_t comfort : 1; // Temperature or Humidity comfort
uint8_t trg_on : 1; // Temperature or Humidity trigger on
uint8_t temp_trg_on : 1; // Temperature trigger on
uint8_t humi_trg_on : 1; // Humidity trigger on
} measured_flg_t;
typedef struct _measured_data_t {
uint16_t count;
int16_t temp; // x 0.01 C
int16_t humi; // x 0.01 %
uint16_t battery_mv; // mV
uint8_t battery; // 0..100 %
uint8_t out_flg; // _measured_flg_t
measured_flg_t flg;
} measured_data_t;
#define send_len_measured_data 10
extern measured_data_t measured_data;
typedef struct _thsensor_coef_t {
uint32_t temp_k;
uint32_t humi_k;
int16_t temp_z;
int16_t humi_z;
} thsensor_coef_t;
typedef int (*psernsor_rd_t)(void);
//typedef void (*psernsor_sm_t)(void);
typedef struct _thsensor_cfg_t {
thsensor_coef_t coef;
uint16_t mid;
uint16_t vid;
uint8_t i2c_addr;
psernsor_rd_t read_sensor;
// psernsor_sm_t start_measure;
} thsensor_cfg_t;
extern thsensor_cfg_t thsensor_cfg;
#define thsensor_cfg_send_size 19
void init_sensor(void);
void start_measure(void);
int read_sensor(void);
#else // (DEV_SERVICES & SERVICE_THS)
typedef struct _measured_data_t {
uint16_t count;
// int16_t temp; // x 0.01 C
// int16_t humi; // x 0.01 %
uint16_t battery_mv; // mV
uint8_t battery; // 0..100 %
} measured_data_t;
extern measured_data_t measured_data;
#endif // (DEV_SERVICES & SERVICE_THS)
#endif // _SENSORS_H_

View file

@ -4,7 +4,7 @@
*/
#include "config.h"
#include "sensors.h"
#include "sensor.h"
measured_data_t measured_data;
@ -14,6 +14,7 @@ measured_data_t measured_data;
#include "gpio.h"
#include "rom_sym_def.h"
#include "dev_i2c.h"
#include "trigger.h"
#define I2C_SPEED 1
@ -95,6 +96,9 @@ int read_sensor(void) {
int ret = 1;
if(thsensor_cfg.i2c_addr && thsensor_cfg.read_sensor != NULL)
ret = thsensor_cfg.read_sensor();
#if (OTA_TYPE == OTA_TYPE_APP) && ((DEV_SERVICES & SERVICE_TH_TRG) || (DEV_SERVICES & SERVICE_SCREEN))
set_trigger_out();
#endif
if(ret)
init_sensor();
return ret;

View file

@ -38,12 +38,13 @@
#include "thservice.h"
#include "thb2_peripheral.h"
#include "bthome_beacon.h"
#include "sensors.h"
#include "sensor.h"
#include "battery.h"
#include "sbp_profile.h"
#include "ble_ota.h"
#include "lcd_th05.h"
#include "logger.h"
#include "trigger.h"
/*********************************************************************
* MACROS
*/
@ -331,6 +332,12 @@ static void init_app_gpio(void)
hal_gpio_write(GPIO_SPWR, 1);
hal_gpioretention_register(GPIO_SPWR);//enable this pin retention
#endif
#if (DEV_SERVICES & SERVICE_TH_TRG)
#ifdef GPIO_TRG
hal_gpio_write(GPIO_TRG, (trg.cfg & TRG_CFG_OUT_INV) != 0);
hal_gpioretention_register(GPIO_TRG);//enable this pin retention
#endif
#endif
}
/*********************************************************************

View file

@ -20,7 +20,7 @@
//#include "hiddev.h"
#include "thservice.h"
#include "sensors.h"
#include "sensor.h"
/*********************************************************************
MACROS
*/

View file

@ -0,0 +1,104 @@
/*
* trigger.c
*
* Created on: 5 февр. 2024 г.
* Author: pvvx
*/
#include "config.h"
#if (OTA_TYPE == OTA_TYPE_APP) && (DEV_SERVICES & SERVICE_THS)
#include "flash.h"
#include "flash_eep.h"
#include "logger.h"
#include "sensor.h"
#include "cmd_parser.h"
#include "trigger.h"
trigger_t trg;
const trigger_t def_trg = {
#if (DEV_SERVICES & SERVICE_SCREEN)
.temp_min = 2000,
.temp_max = 2500,
.humi_min = 3000,
.humi_max = 6000,
#endif
#if (DEV_SERVICES & SERVICE_TH_TRG)
.temp_threshold = 2250,
.humi_threshold = 5000
#endif
};
void set_trigger_out(void) {
#if (DEV_SERVICES & SERVICE_SCREEN)
if (measured_data.temp >= trg.temp_min && measured_data.temp <= trg.temp_max
&& measured_data.humi >= trg.humi_min && measured_data.humi <= trg.humi_max)
measured_data.flg.comfort = true;
else
measured_data.flg.comfort = false;
#endif
#if (DEV_SERVICES & SERVICE_TH_TRG)
if (trg.temp_hysteresis) {
if (measured_data.flg.temp_trg_on) { // temp_out on
if (trg.temp_hysteresis < 0) {
if (measured_data.temp > trg.temp_threshold - trg.temp_hysteresis) {
measured_data.flg.temp_trg_on = false;
}
} else {
if (measured_data.temp < trg.temp_threshold - trg.temp_hysteresis) {
measured_data.flg.temp_trg_on = false;
}
}
} else { // temp_out off
if (trg.temp_hysteresis < 0) {
if (measured_data.temp < trg.temp_threshold + trg.temp_hysteresis) {
measured_data.flg.temp_trg_on = true;
}
} else {
if (measured_data.temp > trg.temp_threshold + trg.temp_hysteresis) {
measured_data.flg.temp_trg_on = true;
}
}
}
} else measured_data.flg.temp_trg_on = false;
if (trg.humi_hysteresis) {
if (measured_data.flg.humi_trg_on) { // humi_out on
if (trg.humi_hysteresis < 0) {
if (measured_data.humi > trg.humi_threshold - trg.humi_hysteresis) {
// humi > threshold
measured_data.flg.humi_trg_on = false;
}
} else { // hysteresis > 0
if (measured_data.humi < trg.humi_threshold - trg.humi_hysteresis) {
// humi < threshold
measured_data.flg.humi_trg_on = false;
}
}
} else { // humi_out off
if (trg.humi_hysteresis < 0) {
if (measured_data.humi < trg.humi_threshold + trg.humi_hysteresis) {
// humi < threshold
measured_data.flg.humi_trg_on = true;
}
} else { // hysteresis > 0
if (measured_data.humi > trg.humi_threshold + trg.humi_hysteresis) {
// humi > threshold
measured_data.flg.humi_trg_on = true;
}
}
}
} else measured_data.flg.humi_trg_on = false;
measured_data.flg.trg_on = measured_data.flg.humi_trg_on || measured_data.flg.humi_trg_on;
#ifdef GPIO_TRG
hal_gpio_fast_write(GPIO_TRG, (trg.cfg & TRG_CFG_OUT_INV)? !measured_data.flg.trg_on : measured_data.flg.trg_on);
#endif
#endif
#ifdef GPIO_INP
measured_data.flg.pin_input = hal_gpio_read(GPIO_INP);
#endif
measured_data.out_flg = *((uint8_t *)&measured_data.flg);
}
#endif // SERVICE_THS

View file

@ -0,0 +1,50 @@
/*
* trigger.h
*
* Created on: 5 февр. 2024 г.
* Author: pvvx
*/
#ifndef _TRIGGER_H_
#define _TRIGGER_H_
#include "config.h"
#if (DEV_SERVICES & SERVICE_THS)
typedef struct _trigger_t {
#if (DEV_SERVICES & SERVICE_SCREEN)
int16_t temp_min; // x0.01°,
int16_t temp_max; // x0.01°,
int16_t humi_min; // x0.01%,
int16_t humi_max; // x0.01%,
#endif
#if (DEV_SERVICES & SERVICE_TH_TRG)
int16_t temp_threshold; // x0.01°, temp threshold
int16_t humi_threshold; // x0.01%, humi threshold
int16_t temp_hysteresis; // temp hysteresis, -327.67..327.67 °
int16_t humi_hysteresis; // humi hysteresis, -327.67..327.67 %
uint8_t cfg;
#endif
}trigger_t;
#if (DEV_SERVICES & SERVICE_SCREEN)
#if (DEV_SERVICES & SERVICE_TH_TRG)
#define trigger_send_size 17
#else
#define trigger_send_size 9
#endif
#else
#if (DEV_SERVICES & SERVICE_TH_TRG)
#define trigger_send_size 9
#else
#define trigger_send_size 0
#endif
#endif
extern trigger_t trg;
extern const trigger_t def_trg;
#define TRG_CFG_OUT_INV 1 // инверсия вывода trg
void set_trigger_out(void);
#endif // SERVICE_THS
#endif /* _TRIGGER_H_ */

View file

@ -1,6 +1,6 @@
<html class="phy6222Class"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>PHY62x2 BTHome v0.8</title>
<title>PHY62x2 BTHome v0.9</title>
<style type="text/css">
/* basic sytles */
@ -454,6 +454,7 @@ var devinfo = {};
var devsrs = {};
var devcfg = {};
var devcfs = {};
var devtrg = {};
var devtime = {};
var devnm = {};
@ -721,7 +722,6 @@ function disableControls(state)
$('btnSetDev').disabled = state;
$('btnGetSens').disabled = state;
$('btnSetSens').disabled = state;
$('btnGetDevTime').disabled = state;
$('btnSetDevTime').disabled = state;
$('btnReadAddr').disabled = state;
@ -1180,6 +1180,15 @@ function customBlkParse(value) {
devsrs.sw_version = value.getUint16(4, true);
devsrs.dev_spec_data = value.getUint16(6, true);
devsrs.services = value.getUint32(8, true);
if((devsrs.services & 0x00000020) != 0) {
$("tbComfort").disabled = false;
} else {
$("tbComfort").disabled = true;
}
if((devsrs.services & 0x00004000) != 0)
$("tbTrigger").disabled = false;
else
$("tbTrigger").disabled = true;
addLog("Dev info # hw: "+hex(devsrs.hw_version,4)+", sw: "+hex(devsrs.sw_version,4)+", services: "+hex(devsrs.services,8)+", sd: "+hex(devsrs.dev_spec_data, 4));
} else if(blkId == 0x35){
if(flg_memo_act) {
@ -1347,6 +1356,37 @@ function customBlkParse(value) {
}
}
}
} else if((blkId == 0x44) && (len > 8)) {
if(len != 9) {
devtrg.temp_min = value.getInt16(1, true);
devtrg.temp_max = value.getInt16(3, true);
devtrg.humi_min = value.getInt16(5, true);
devtrg.humi_max = value.getInt16(7, true);
if($("tbComfort").disabled == false && (devsrs.services & 0x00000020) != 0) { // SERVICE_SCREEN
$("inputTempMin").value = (devtrg.temp_min/100.0).toFixed(2);
$("inputTempMax").value = (devtrg.temp_max/100.0).toFixed(2);
$("inputHumiMin").value = (devtrg.humi_min/100.0).toFixed(2);
$("inputHumiMax").value = (devtrg.humi_max/100.0).toFixed(2);
}
}
let x = 0;
if(len == 10) x = 1;
else if(len >= 18) x = 9;
if(x > 0) {
devtrg.temp_threshold = value.getInt16(x, true);
devtrg.humi_threshold = value.getInt16(x+2, true);
devtrg.temp_hysteresis = value.getInt16(x+4, true);
devtrg.humi_hysteresis = value.getInt16(x+6, true);
devtrg.flg = value.getUint8(x+8);
if($("tbTrigger").disabled == false && (devsrs.services & 0x00004000) != 0) { // SERVICE_TH_TRG
$("chbInvOut").checked = (devtrg.flg & 1) != 0;
$("inputTempThr").value = (devtrg.temp_threshold/100.0).toFixed(2);
$("inputHumiThr").value = (devtrg.humi_threshold/100.0).toFixed(2);
$("inputTempHsr").value = (devtrg.temp_hysteresis/100.0).toFixed(2);
$("inputHumiHsr").value = (devtrg.humi_hysteresis/100.0).toFixed(2);
}
}
addLog("Строка настроек триггера: "+ bytesToHex(value.buffer));
} else if(blkId == 0x20 && len >= 8) {
devcmf.tmp_lo = value.getInt16(1, true); // temp lo
devcmf.tmp_hi = value.getInt16(3, true); // temp hi
@ -1420,14 +1460,10 @@ function getSensCfg() {
}
function ChowConfig() {
$('chbCfgFlgNotify').checked = devcfg.flg & 1 != 0;
if((devsrs.services & 0x00000020) != 0) {
$('chbCfgFlgClock').enabled = true;
$('chbCfgFlgClock').checked = devcfg.flg & 2 != 0;
} else {
$('chbCfgFlgClock').enabled = false;
$('chbCfgFlgClock').checked = false;
}
$('chbCfgFlgNotify').checked = (devcfg.flg & 1) != 0;
$('chbCfgFlgClock').checked = (devcfg.flg & 2) != 0;
$('chbCfgFlgSmiley').checked = (devcfg.flg & 4) != 0;
$('chbCfgFlgTrg').checked = (devcfg.flg & 8) != 0;
let rfm = 31;
el = $('selRfTxPwr');
for(let n = 0; n < el.options.length; n++) if(el.options[n].value >= devcfg.rf_tx_power) rfm = el.options[n].value;
@ -1442,9 +1478,10 @@ function ChowConfig() {
function setDevCfg() {
if(cmdCharacteristic != null) {
// addLog("setDevCfg...");
devcfg.flg = 0
| $('chbCfgFlgNotify').checked
| $('chbCfgFlgClock').checked;
devcfg.flg = ($('chbCfgFlgNotify').checked) ? 1 : 0;
devcfg.flg |= ($('chbCfgFlgClock').checked) ? 2 : 0;
devcfg.flg |= ($('chbCfgFlgSmiley').checked) ? 4 : 0;
devcfg.flg |= ($('chbCfgFlgTrg').checked) ? 8 : 0;
devcfg.rf_tx_power = $('selRfTxPwr').value & 0x3f; // 0..0x1f -> -20..+5 dBm ? нелинейное 0x1f = +0 дБм
let connect_latency = parseInt($('inputLat').value); // = (connect_latency + 1)*30 ms
if (connect_latency < 0) {
@ -1552,6 +1589,56 @@ function setDevMAC() {
}
}
function getTrgCfg() {
if(cmdCharacteristic != null) {
cmdCharacteristic.writeValue(new Uint8Array([0x44])).catch(error => { console.log(error); addLog("getTrgCfg() error!"); });
}
}
function setTrgCfg() {
if(cmdCharacteristic != null) {
let len = 0;
if((devsrs.services & 0x00000020) != 0) len = 8;
if((devsrs.services & 0x00004000) != 0) len += 9;
if(len > 0) {
let blk = new Uint8Array(len + 1);
blk[0] = 0x44;
let idx = 0;
if(len != 9) {
devtrg.temp_min = Math.round($("inputTempMin").value * 100);
devtrg.temp_max = Math.round($("inputTempMax").value * 100);
devtrg.humi_min = Math.round($("inputHumiMin").value * 100);
devtrg.humi_max = Math.round($("inputHumiMax").value * 100);
blk[1] = devtrg.temp_min & 0xff;
blk[2] = (devtrg.temp_min >> 8) & 0xff;
blk[3] = devtrg.temp_max & 0xff;
blk[4] = (devtrg.temp_max >> 8) & 0xff;
blk[5] = devtrg.humi_min & 0xff;
blk[6] = (devtrg.humi_min >> 8) & 0xff;
blk[7] = devtrg.humi_max & 0xff;
blk[8] = (devtrg.humi_max >> 8) & 0xff;
idx = 9;
}
if(len > 8) {
devtrg.temp_threshold = Math.round($("inputTempThr").value * 100);
devtrg.humi_threshold = Math.round($("inputHumiThr").value * 100);
devtrg.temp_hysteresis = Math.round($("inputTempHsr").value * 100);
devtrg.humi_hysteresis = Math.round($("inputHumiHsr").value * 100);
devtrg.flg = ($("chbInvOut").checked)? 1: 0;
blk[idx+0] = devtrg.temp_threshold & 0xff;
blk[idx+1] = (devtrg.temp_threshold >> 8) & 0xff;
blk[idx+2] = devtrg.humi_threshold & 0xff;
blk[idx+3] = (devtrg.humi_threshold >> 8) & 0xff;
blk[idx+4] = devtrg.temp_hysteresis & 0xff;
blk[idx+5] = (devtrg.temp_hysteresis >> 8) & 0xff;
blk[idx+6] = devtrg.humi_hysteresis & 0xff;
blk[idx+7] = (devtrg.humi_hysteresis >> 8) & 0xff;
blk[idx+8] = devtrg.flg & 0xff;
}
cmdCharacteristic.writeValue(blk).catch(error => { console.log(error); addLog("setTrgCfg() error!"); });
}
}
}
function readFile(file) {
@ -1766,7 +1853,9 @@ function ShowGrf(temp, humi) {
<tr align="center">
<td>
Notify измерений <input type="checkbox" id="chbCfgFlgNotify"><br>
Показ часов <input type="checkbox" id="chbCfgFlgClock">
Показ часов <input type="checkbox" id="chbCfgFlgClock"><br>
Показывать Смайлик <input type="checkbox" id="chbCfgFlgSmiley"><br>
Показывать Триггер <input type="checkbox" id="chbCfgFlgTrg">
</td>
<td>
<select id="selRfTxPwr">
@ -1825,7 +1914,6 @@ function ShowGrf(temp, humi) {
</tr>
</table>
<br>
<!--
Поправочные коэффициенты:
Температуры: <input size="8" type="text" id="inputTempK" maxlength="8">
@ -1843,7 +1931,29 @@ function ShowGrf(temp, humi) {
<button type="button"id="btnGetSens" onclick="getSensCfg()">Прочитать</button>
<button type="button"id="btnSetSens" onclick="setSensCfg()">Записать</button><br>
<hr>
<button type="button" id="btnGetDevTime" onclick="getDevTime()">Время устройства</button>
<table id="tbComfort" disabled="true">
<tr>
<td>Комфорт: </td>
<td>Температура от <input size="4" type="text" id="inputTempMin" maxlength="4" title="Минимальная температура">
до <input size="4" type="text" id="inputTempMax" maxlength="4" title="Максимальная температура"> °C,</td>
<td>Влажность от <input size="4" type="text" id="inputHumiMin" maxlength="4" title="Минимальная влажность">
до <input size="4" type="text" id="inputHumiMax" maxlength="4" title="Максимальная влажность"> %RH</td>
</tr>
</table>
<table id="tbTrigger" disabled="true">
<tr>
<td>Триггер: </td>
<td>Температура: <input size="4" type="text" id="inputTempThr" maxlength="4" title="Температура переключения"> °C</td>
<td>Влажность: <input size="4" type="text" id="inputHumiThr" maxlength="4" title="Влажность переключения"> %RH, </td>
<td>Гистерезис: <input size="4" type="text" id="inputTempHsr" maxlength="4" title="Гистерезис температуры"> °C</td>
<td><input size="4" type="text" id="inputHumiHsr" maxlength="4" title="Гистерезис влажности"> %RH</td>
<td>Инверсия вывода <input type="checkbox" id="chbInvOut"></td>
<td>
</tr>
</table>
<button type="button"id="btnGetTrg" onclick="getTrgCfg()">Прочитать</button>
<button type="button"id="btnSetTrg" onclick="setTrgCfg()">Записать</button><br>
<hr>
<button type="button" id="btnSetDevTime" onclick="setDevTime()">Установить время</button>
</div>