Merge branch 'development' into pre-release-11.1

This commit is contained in:
Theo Arends 2022-04-10 12:06:50 +02:00
commit 0cbc1681d2
26 changed files with 6210 additions and 206 deletions

View File

@ -6,15 +6,23 @@ All notable changes to this project will be documented in this file.
## [11.1.0] 20220413
- Release Ostara
## [11.0.0.6] 20220413
## [11.0.0.7] 20220413
### Added
- Commands ``Sensor34 10 <valueA>`` and ``Sensor34 11 <valueB>`` to use HX711 absolute weight conversion (#15292)
- HX711 command ``Sensor34 10 0|1|<weight in gram>`` to set HX711 fixed tare (0 = use auto tare, 1 = use calibrated tare, Any other value is user selected tare)
### Changed
- NeoPool: boost command with redox control state, relay and aux detail display
- HX711 removed command ``Sensor34 7`` as now active tare is persistent resulting in calculated current weight
- HX711 commands ``Sensor34 11 <valueA>`` and ``Sensor34 12 <valueB>`` to use HX711 absolute weight conversion (#15292)
## [11.0.0.6] 20220409
### Added
- HX711 commands ``Sensor34 10 <valueA>`` and ``Sensor34 11 <valueB>`` to use HX711 absolute weight conversion (#15292)
### Changed
- NeoPool boost command with redox control state, relay and aux detail display
### Fixed
- NeoPool filtration state
- NeoPool filtration state and speed display
## [11.0.0.5] 20220407
### Added

View File

@ -112,7 +112,8 @@ The latter links can be used for OTA upgrades too like ``OtaUrl http://ota.tasmo
- Command ``RfTimeout 100..60000`` to disable duplicate RfReceive. Default 1000 [#15061](https://github.com/arendst/Tasmota/issues/15061)
- Command ``IfxSensor 1`` to send non-teleperiod data to influxdb
- Commands ``Sensor12 D0 .. D5, S0 .. S5`` allowing differential or single-ended modes [#15001](https://github.com/arendst/Tasmota/issues/15001)
- Commands ``Sensor34 10 <valueA>`` and ``Sensor34 11 <valueB>`` to use HX711 absolute weight conversion [#15292](https://github.com/arendst/Tasmota/issues/15292)
- HX711 command ``Sensor34 10 0|1|<weight in gram>`` to set HX711 fixed tare (0 = use auto tare, 1 = use calibrated tare, Any other value is user selected tare)
- HX711 commands ``Sensor34 11 <valueA>`` and ``Sensor34 12 <valueB>`` to use HX711 absolute weight conversion [#15292](https://github.com/arendst/Tasmota/issues/15292)
- NeoPool commands ``NPpHMin``, ``NPpHMax``, ``NPpH``, ``NPRedox``, ``NPHydrolysis``, ``NPIonization``, ``NPChlorine`` and ``NPControl`` [#15015](https://github.com/arendst/Tasmota/issues/15015)
- NeoPool system voltages display
- TasmotaSerial implement ``end()``
@ -139,6 +140,7 @@ The latter links can be used for OTA upgrades too like ``OtaUrl http://ota.tasmo
- Extent number of pulsetimers from 8 to 32 [#8266](https://github.com/arendst/Tasmota/issues/8266)
- Consolidate three RTC chip drivers (DS3231, BM8563, PCF85363) into one driver updating RTC as soon as possible after restart
- Removed command ``Sensor33`` and replaced by ``RtcNtpserver``
- HX711 removed command ``Sensor34 7`` as now active tare is persistent resulting in calculated current weight
- Remove support for Internet Explorer by allowing ECMAScript6 syntax using less JavaScript code bytes [#15280](https://github.com/arendst/Tasmota/issues/15280)
- DS3231 I2C address define ``USE_RTC_ADDR`` into ``DS3231_ADDRESS``
- Display of energy values in GUI use columns when define ``USE_ENERGY_COLUMN_GUI`` is enabled (default)

View File

@ -50,6 +50,9 @@ be_extern_native_module(animate);
be_extern_native_module(lv);
be_extern_native_module(lv_extra);
be_extern_native_module(lv_tasmota);
#ifdef USE_LVGL_OPENHASP
be_extern_native_module(openhasp);
#endif // USE_LVGL_OPENHASP
#endif // USE_LVGL
/* user-defined modules declare start */
@ -132,6 +135,9 @@ BERRY_LOCAL const bntvmodule* const be_module_table[] = {
&be_native_module(lv),
&be_native_module(lv_extra),
&be_native_module(lv_tasmota),
#ifdef USE_LVGL_OPENHASP
&be_native_module(openhasp),
#endif // USE_LVGL_OPENHASP
#endif // USE_LVGL
#ifdef USE_ENERGY_SENSOR
&be_native_module(energy),

View File

@ -33,6 +33,12 @@ extern "C" {
.next = (uint32_t)(_next) & 0xFFFFFF \
}
#define be_const_key_literal(_str, _next) { \
.v.c = be_str_literal(_str), \
.type = BE_STRING, \
.next = (uint32_t)(_next) & 0xFFFFFF \
}
#define be_const_key_int(_i, _next) { \
.v.i = _i, \
.type = BE_INT, \
@ -230,6 +236,13 @@ const bntvmodule be_native_module(_module) = { \
BE_STRING \
}
#define be_nested_str_literal(_name_) \
{ \
{ .s=(be_nested_const_str(_name_, _hash, sizeof(_name_)-1 ))\
}, \
BE_STRING \
}
#define be_str_literal(_str) \
be_nested_const_str(_str, 0, sizeof(_str)-1 )

View File

@ -94,9 +94,63 @@ static void toidentifier(char *to, const char *p)
*to = 0; // final NULL
}
static void m_solidify_bvalue(bvm *vm, bvalue * value, const char *classname, const char *key);
static void m_solidify_map(bvm *vm, bmap * map, const char *class_name)
/********************************************************************\
* Encode string as literals with simple rules
*
* Encode specifically \\, \n, \"
* All other characters outside of 0x20-0x7F is escaped with \x..
\********************************************************************/
static unsigned toliteral_length(const char *s)
{
unsigned len = 1;
const char * p = s;
while (*p) {
if (*p == '\n' || *p == '\\' || *p == '"') {
len += 2;
} else if (*p >= 0x20 && (*p & 0x80) == 0) {
len++;
} else {
len += 4; /* encode as \x.. */
}
p++;
}
return len;
}
static void toliteral(char *to, const char *p)
{
while (*p) {
if (*p == '\n') {
to[0] = '\\';
to[1] = 'n';
to += 2;
} else if (*p == '\\') {
to[0] = '\\';
to[1] = '\\';
to += 2;
} else if (*p == '"') {
to[0] = '\\';
to[1] = '"';
to += 2;
} else if (*p >= 0x20 && (*p & 0x80) == 0) {
*to = *p;
to++;
} else {
to[0] = '\\';
to[1] = 'x';
to[2] = hexdigit((*p & 0xF0) >> 4);
to[3] = hexdigit(*p & 0x0F);
to += 4;
}
p++;
}
*to = 0; // final NULL
}
static void m_solidify_bvalue(bvm *vm, bbool str_literal, bvalue * value, const char *classname, const char *key);
static void m_solidify_map(bvm *vm, bbool str_literal, bmap * map, const char *class_name)
{
// compact first
be_map_compact(vm, map);
@ -116,14 +170,21 @@ static void m_solidify_map(bvm *vm, bmap * map, const char *class_name)
if (node->key.type == BE_STRING) {
/* convert the string literal to identifier */
const char * key = str(node->key.v.s);
size_t id_len = toidentifier_length(key);
char id_buf[id_len];
toidentifier(id_buf, key);
logfmt(" { be_const_key(%s, %i), ", id_buf, key_next);
m_solidify_bvalue(vm, &node->value, class_name, str(node->key.v.s));
if (!str_literal) {
size_t id_len = toidentifier_length(key);
char id_buf[id_len];
toidentifier(id_buf, key);
logfmt(" { be_const_key(%s, %i), ", id_buf, key_next);
} else {
size_t id_len = toliteral_length(key);
char id_buf[id_len];
toliteral(id_buf, key);
logfmt(" { be_const_key_literal(\"%s\", %i), ", id_buf, key_next);
}
m_solidify_bvalue(vm, str_literal, &node->value, class_name, str(node->key.v.s));
} else if (node->key.type == BE_INT) {
logfmt(" { be_const_key_int(%i, %i), ", node->key.v.i, key_next);
m_solidify_bvalue(vm, &node->value, class_name, NULL);
m_solidify_bvalue(vm, str_literal, &node->value, class_name, NULL);
} else {
char error[64];
snprintf(error, sizeof(error), "Unsupported type in key: %i", node->key.type);
@ -136,21 +197,21 @@ static void m_solidify_map(bvm *vm, bmap * map, const char *class_name)
}
static void m_solidify_list(bvm *vm, blist * list, const char *class_name)
static void m_solidify_list(bvm *vm, bbool str_literal, blist * list, const char *class_name)
{
logfmt(" be_nested_list(%i,\n", list->count);
logfmt(" ( (struct bvalue*) &(const bvalue[]) {\n");
for (int i = 0; i < list->count; i++) {
logfmt(" ");
m_solidify_bvalue(vm, &list->data[i], class_name, "");
m_solidify_bvalue(vm, str_literal, &list->data[i], class_name, "");
logfmt(",\n");
}
logfmt(" }))"); // TODO need terminal comma?
}
// pass key name in case of class, or NULL if none
static void m_solidify_bvalue(bvm *vm, bvalue * value, const char *classname, const char *key)
static void m_solidify_bvalue(bvm *vm, bbool str_literal, bvalue * value, const char *classname, const char *key)
{
int type = var_primetype(value);
switch (type) {
@ -188,10 +249,17 @@ static void m_solidify_bvalue(bvm *vm, bvalue * value, const char *classname, co
if (len >= 255) {
be_raise(vm, "internal_error", "Strings greater than 255 chars not supported yet");
}
size_t id_len = toidentifier_length(str);
char id_buf[id_len];
toidentifier(id_buf, str);
logfmt("be_nested_str(%s)", id_buf);
if (!str_literal) {
size_t id_len = toidentifier_length(str);
char id_buf[id_len];
toidentifier(id_buf, str);
logfmt("be_nested_str(%s)", id_buf);
} else {
size_t id_len = toliteral_length(str);
char id_buf[id_len];
toliteral(id_buf, str);
logfmt("be_nested_str_literal(\"%s\")", id_buf);
}
}
break;
case BE_CLOSURE:
@ -235,16 +303,16 @@ static void m_solidify_bvalue(bvm *vm, bvalue * value, const char *classname, co
} else {
logfmt(" be_const_list( * ");
}
m_solidify_bvalue(vm, &ins->members[0], classname, key);
m_solidify_bvalue(vm, str_literal, &ins->members[0], classname, key);
logfmt(" ) } ))");
}
}
break;
case BE_MAP:
m_solidify_map(vm, (bmap *) var_toobj(value), classname);
m_solidify_map(vm, str_literal, (bmap *) var_toobj(value), classname);
break;
case BE_LIST:
m_solidify_list(vm, (blist *) var_toobj(value), classname);
m_solidify_list(vm, str_literal, (blist *) var_toobj(value), classname);
break;
default:
{
@ -255,24 +323,24 @@ static void m_solidify_bvalue(bvm *vm, bvalue * value, const char *classname, co
}
}
static void m_solidify_subclass(bvm *vm, bclass *cl, int builtins);
static void m_solidify_subclass(bvm *vm, bbool str_literal, bclass *cl, int builtins);
/* solidify any inner class */
static void m_solidify_proto_inner_class(bvm *vm, bproto *pr, int builtins)
static void m_solidify_proto_inner_class(bvm *vm, bbool str_literal, bproto *pr, int builtins)
{
// parse any class in constants to output it first
if (pr->nconst > 0) {
for (int k = 0; k < pr->nconst; k++) {
if (var_type(&pr->ktab[k]) == BE_CLASS) {
// output the class
m_solidify_subclass(vm, (bclass*) var_toobj(&pr->ktab[k]), builtins);
m_solidify_subclass(vm, str_literal, (bclass*) var_toobj(&pr->ktab[k]), builtins);
}
}
}
}
static void m_solidify_proto(bvm *vm, bproto *pr, const char * func_name, int builtins, int indent)
static void m_solidify_proto(bvm *vm, bbool str_literal, bproto *pr, const char * func_name, int builtins, int indent)
{
// const char * func_name = str(pr->name);
// const char * func_source = str(pr->source);
@ -302,7 +370,7 @@ static void m_solidify_proto(bvm *vm, bproto *pr, const char * func_name, int bu
size_t sub_len = strlen(func_name) + 10;
char sub_name[sub_len];
snprintf(sub_name, sizeof(sub_name), "%s_%d", func_name, i);
m_solidify_proto(vm, pr->ptab[i], sub_name, builtins, indent+2);
m_solidify_proto(vm, str_literal, pr->ptab[i], sub_name, builtins, indent+2);
logfmt(",\n");
}
logfmt("%*s}),\n", indent, "");
@ -315,7 +383,7 @@ static void m_solidify_proto(bvm *vm, bproto *pr, const char * func_name, int bu
logfmt("%*s( &(const bvalue[%2d]) { /* constants */\n", indent, "", pr->nconst);
for (int k = 0; k < pr->nconst; k++) {
logfmt("%*s/* K%-3d */ ", indent, "", k);
m_solidify_bvalue(vm, &pr->ktab[k], NULL, NULL);
m_solidify_bvalue(vm, str_literal, &pr->ktab[k], NULL, NULL);
logfmt(",\n");
}
logfmt("%*s}),\n", indent, "");
@ -324,12 +392,18 @@ static void m_solidify_proto(bvm *vm, bproto *pr, const char * func_name, int bu
}
/* convert the string literal to identifier */
{
if (!str_literal) {
const char * key = str(pr->name);
size_t id_len = toidentifier_length(key);
char id_buf[id_len];
toidentifier(id_buf, key);
logfmt("%*s&be_const_str_%s,\n", indent, "", id_buf);
} else {
const char * key = str(pr->name);
size_t id_len = toliteral_length(key);
char id_buf[id_len];
toliteral(id_buf, key);
logfmt("%*sbe_str_literal(\"%s\"),\n", indent, "", id_buf);
}
// hard-code source as "solidified" for solidified
logfmt("%*s&be_const_str_solidified,\n", indent, "");
@ -356,7 +430,7 @@ static void m_solidify_proto(bvm *vm, bproto *pr, const char * func_name, int bu
}
static void m_solidify_closure(bvm *vm, bclosure *cl, const char * classname, int builtins)
static void m_solidify_closure(bvm *vm, bbool str_literal, bclosure *cl, const char * classname, int builtins)
{
bproto *pr = cl->proto;
const char * func_name = str(pr->name);
@ -368,7 +442,7 @@ static void m_solidify_closure(bvm *vm, bclosure *cl, const char * classname, in
int indent = 2;
m_solidify_proto_inner_class(vm, pr, builtins);
m_solidify_proto_inner_class(vm, str_literal, pr, builtins);
logfmt("\n");
logfmt("/********************************************************************\n");
@ -384,7 +458,7 @@ static void m_solidify_closure(bvm *vm, bclosure *cl, const char * classname, in
func_name_id);
}
m_solidify_proto(vm, pr, func_name, builtins, indent);
m_solidify_proto(vm, str_literal, pr, func_name, builtins, indent);
logfmt("\n");
// closure
@ -392,7 +466,7 @@ static void m_solidify_closure(bvm *vm, bclosure *cl, const char * classname, in
logfmt("/*******************************************************************/\n\n");
}
static void m_solidify_subclass(bvm *vm, bclass *cl, int builtins)
static void m_solidify_subclass(bvm *vm, bbool str_literal, bclass *cl, int builtins)
{
const char * class_name = str(cl->name);
@ -403,7 +477,7 @@ static void m_solidify_subclass(bvm *vm, bclass *cl, int builtins)
while ((node = be_map_next(cl->members, &iter)) != NULL) {
if (var_isstr(&node->key) && var_isclosure(&node->value)) {
bclosure *f = var_toobj(&node->value);
m_solidify_closure(vm, f, class_name, builtins);
m_solidify_closure(vm, str_literal, f, class_name, builtins);
}
}
}
@ -427,22 +501,32 @@ static void m_solidify_subclass(bvm *vm, bclass *cl, int builtins)
}
if (cl->members) {
m_solidify_map(vm, cl->members, class_name);
m_solidify_map(vm, str_literal, cl->members, class_name);
logfmt(",\n");
} else {
logfmt(" NULL,\n");
}
logfmt(" be_str_literal(\"%s\")\n", class_name);
if (!str_literal) {
size_t id_len = toidentifier_length(class_name);
char id_buf[id_len];
toidentifier(id_buf, class_name);
logfmt(" &be_const_str_%s,\n", id_buf);
} else {
size_t id_len = toliteral_length(class_name);
char id_buf[id_len];
toliteral(id_buf, class_name);
logfmt(" be_str_literal(\"%s\")\n", id_buf);
}
logfmt(");\n");
}
static void m_solidify_class(bvm *vm, bclass *cl, int builtins)
static void m_solidify_class(bvm *vm, bbool str_literal, bclass *cl, int builtins)
{
const char * class_name = str(cl->name);
m_solidify_subclass(vm, cl, builtins);
m_solidify_subclass(vm, str_literal, cl, builtins);
logfmt("/*******************************************************************/\n\n");
logfmt("void be_load_%s_class(bvm *vm) {\n", class_name);
@ -452,7 +536,7 @@ static void m_solidify_class(bvm *vm, bclass *cl, int builtins)
logfmt("}\n");
}
static void m_solidify_module(bvm *vm, bmodule *ml, int builtins)
static void m_solidify_module(bvm *vm, bbool str_literal, bmodule *ml, int builtins)
{
const char * module_name = be_module_name(ml);
if (!module_name) { module_name = ""; }
@ -464,11 +548,11 @@ static void m_solidify_module(bvm *vm, bmodule *ml, int builtins)
while ((node = be_map_next(ml->table, &iter)) != NULL) {
if (var_isstr(&node->key) && var_isclosure(&node->value)) {
bclosure *f = var_toobj(&node->value);
m_solidify_closure(vm, f, module_name, builtins);
m_solidify_closure(vm, str_literal, f, module_name, builtins);
}
if (var_isstr(&node->key) && var_isclass(&node->value)) {
bclass *cl = var_toobj(&node->value);
m_solidify_subclass(vm, cl, builtins);
m_solidify_subclass(vm, str_literal, cl, builtins);
}
}
}
@ -483,7 +567,7 @@ static void m_solidify_module(bvm *vm, bmodule *ml, int builtins)
logfmt(" \"%s\",\n", module_name);
if (ml->table) {
m_solidify_map(vm, ml->table, module_name);
m_solidify_map(vm, str_literal, ml->table, module_name);
logfmt("\n");
} else {
logfmt(" NULL,\n");
@ -501,12 +585,16 @@ static int m_dump(bvm *vm)
{
if (be_top(vm) >= 1) {
bvalue *v = be_indexof(vm, 1);
bbool str_literal = bfalse;
if (be_top(vm) >= 2) {
str_literal = be_tobool(vm, 2);
}
if (var_isclosure(v)) {
m_solidify_closure(vm, var_toobj(v), NULL, be_builtin_count(vm));
m_solidify_closure(vm, str_literal, var_toobj(v), NULL, be_builtin_count(vm));
} else if (var_isclass(v)) {
m_solidify_class(vm, var_toobj(v), be_builtin_count(vm));
m_solidify_class(vm, str_literal, var_toobj(v), be_builtin_count(vm));
} else if (var_ismodule(v)) {
m_solidify_module(vm, var_toobj(v), be_builtin_count(vm));
m_solidify_module(vm, str_literal, var_toobj(v), be_builtin_count(vm));
} else {
be_raise(vm, "value_error", "unsupported type");
}

View File

@ -875,6 +875,11 @@ newframe: /* a new call frame */
}
var_setinstance(&a[1], obj); /* replace superinstance by lowest subinstance */
}
} else if (var_isclass(a)) {
/* in this case we have a class in a static or non-static member */
/* it's always treated like a statif function */
a[1] = result;
var_settype(a, NOT_METHOD);
} else {
vm_error(vm, "attribute_error",
"class '%s' has no method '%s'",

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@ -1,6 +1,6 @@
# start openhasp
# package with
# zip -j -0 openhasp.tapp openhasp_core/*
# rm openhasp.tapp; zip -j -0 openhasp.tapp openhasp_core/*
import openhasp
# defer start to make sure all modules and tapp applications were loaded first

View File

@ -3,7 +3,28 @@
# use `import openhasp` and set the JSONL definitions in `pages.jsonl`
#
# As an optimization `0 #- lv.PART_MAIN | lv.STATE_DEFAULT -#` is replaced with `0`
#
#################################################################################
# How to solidify (needs an ESP32 with PSRAM)
#-
import path
path.remove("openhasp.bec")
import solidify
var openhasp
load('openhasp.be')
var classes = [
"page", "obj", "scr",
"btn", "switch", "checkbox",
"label", "spinner", "line", "img", "roller", "btnmatrix",
"bar", "slider", "arc", "textarea", "dropdown"
]
for c:classes
solidify.dump(openhasp.OpenHASP.("lvh_"+c), true)
end
solidify.dump(openhasp, true)
-#
var openhasp = module("openhasp")
#################################################################################
@ -56,8 +77,6 @@ class lvh_obj
"radius": "style_radius",
"border_side": "style_border_side",
"border_width": "style_border_width",
"bg_opa": "style_bg_opa",
"border_width": "style_border_width",
"line_width": nil, # depends on class
"line_width1": nil, # depends on class
"action": nil, # store the action in self.action
@ -476,7 +495,15 @@ class lvh_obj
# self.check_label()
var font
if type(t) == 'int'
font = lv.font_robotocondensed_latin1(t)
try
font = lv.font_embedded("robotocondensed", t)
except ..
try
font = lv.font_embedded("montserrat", t)
except ..
return
end
end
elif type(t) == 'string'
import string
var fn_split = string.split(t, '-')
@ -981,7 +1008,8 @@ class lvh_page
end
# page object is also stored in the object map at id `0` as instance of `lvg_scr`
var obj_scr = lvh_scr(nil, self, nil, self._lv_scr) # store screen in a virtual object
var lvh_scr_class = self._oh.lvh_scr
var obj_scr = lvh_scr_class(nil, self, nil, self._lv_scr) # store screen in a virtual object
self._obj_id[0] = obj_scr
# create a global for this page of form p<page_number>, ex `p1`
@ -1068,7 +1096,7 @@ class OpenHASP
var dark # (bool) use dark theme?
var hres, vres # (int) resolution
var scr # (lv_obj) default LVGL screen
var r16, r20 # (lv_font) robotocondensed fonts size 16 and 20
var r16 # (lv_font) robotocondensed fonts size 16
# openhasp objects
var lvh_pages # (list of lvg_page) list of pages
var lvh_page_cur_idx # (int) current page index number
@ -1077,6 +1105,7 @@ class OpenHASP
# assign lvh_page to a static attribute
static lvh_page = lvh_page
static lvh_scr = lvh_scr
# assign all classes as static attributes
static lvh_btn = lvh_btn
static lvh_switch = lvh_switch
@ -1141,8 +1170,11 @@ class OpenHASP
self.vres = lv.get_ver_res() # ex: 240
self.scr = lv.scr_act() # LVGL default screean object
self.r20 = lv.font_robotocondensed_latin1(20) # // TODO what if does not exist
self.r16 = lv.font_robotocondensed_latin1(16) # // TODO what if does not exist
try
self.r16 = lv.font_embedded("robotocondensed", 16) # TODO what if does not exist
except ..
self.r16 = lv.font_embedded("montserrat", 14) # TODO what if does not exist
end
# set the theme for OpenHASP
var th2 = lv.theme_openhasp_init(0, lv.color(0xFF00FF), lv.color(0x303030), self.dark, self.r16)
@ -1424,7 +1456,7 @@ class OpenHASP
var lv_cl = introspect.get(global, obj_type)
if lv_cl != nil && type(lv_cl) == 'class'
lv_instance = lv_cl(parent_lvgl)
obj_class = lvh_obj # use the basic lvh_obj component to encapsulate
obj_class = self.lvh_obj # use the basic lvh_obj component to encapsulate
end
end
@ -1433,7 +1465,7 @@ class OpenHASP
var lv_cl = introspect.module(obj_type)
if lv_cl != nil && type(lv_cl) == 'class'
lv_instance = lv_cl(parent_lvgl)
obj_class = lvh_obj # use the basic lvh_obj component to encapsulate
obj_class = self.lvh_obj # use the basic lvh_obj component to encapsulate
end
end
@ -1483,7 +1515,8 @@ openhasp.OpenHASP = OpenHASP
# This means that the object is never garbage collected
#
openhasp.init = def (m) # `init(m)` is called during first `import openhasp`
return openhasp.OpenHASP()
var oh = m.OpenHASP
return oh()
end
return openhasp

View File

@ -2,19 +2,18 @@
// compressed by tools/unishox/compress-html-uncompressed.py
/////////////////////////////////////////////////////////////////////
const size_t HTTP_SCRIPT_TEMPLATE_SIZE = 297;
const size_t HTTP_SCRIPT_TEMPLATE_SIZE = 288;
const char HTTP_SCRIPT_TEMPLATE_COMPRESSED[] PROGMEM = "\x30\x2F\x83\xAD\xCE\x41\x08\x77\x45\x9D\x46\x0E\xF1\xED\x33\xBF\xA3\x61\xF3\x98"
"\xFA\x23\x61\x0D\x20\x88\x55\x50\xC2\xFB\x35\x0B\x7E\xA3\xBA\x77\x8F\x06\xC3\xA6"
"\x77\xDD\x88\x65\xEA\xBA\x61\x8A\xBE\x1E\x67\xC3\xBA\x77\x8F\x87\xE1\xED\xD3\x07"
"\x76\x85\x6F\x8E\x9F\x76\x21\x91\x7A\xAE\x99\xF0\xF8\x73\x0F\xD1\xFA\x2A\x2B\x15"
"\xBE\x3A\x7A\xAE\x85\xF8\xF8\x7C\x39\x4D\x9D\xE3\xDA\x40\x83\x82\x1D\xE3\xC1\xEE"
"\x3D\xC7\x83\x61\xD3\x06\x3E\x3B\xA7\xD9\x0F\x13\x2A\x2B\x3E\xCE\xA1\x67\x55\x7C"
"\x5B\x3B\xC7\x83\x61\xD3\xCF\x84\x3B\xA7\x78\xF0\x7B\x8C\xEF\xE8\x33\xC0\x22\x6F"
"\x66\xC3\x90\xEE\x90\xE0\x41\xDE\x74\xEA\x35\x9D\x43\xC7\x51\xA1\xD5\x87\x8C\x3E"
"\x0E\x3A\x7D\xF8\x66\x77\x99\x53\x36\x51\xD3\xC3\x02\xDA\x3B\xA7\x61\xEE\x39\x0E"
"\xC3\xBC\x78\x23\x43\xE6\x1D\x3C\x2B\x4C\x51\xDD\x3B\xC7\x8D\x30\x77\x58\xE3\xBA"
"\x7D\xF8\xE4\x3E\xCE\xF1\xD0\x8C\xEC\x21\x6C\xF8\x7C\x3E\xCF\xB3\xBC\x7B\x41\x2A"
"\x2B\x81\xA1\xE0\xF7\x0F\x02\x2E\x22\x08\x59\x49\xF6\x75\x1F\x67\x78\xF1\x9E\x3E"
"\x1E\xC3";
"\x74\xD8\x74\xFB\xB1\x0C\x8B\xD5\x74\xCF\x87\xC3\x98\x7E\x8F\xD1\x1B\x0E\x9E\xAB"
"\xA1\x7E\x3E\x1F\x0E\x53\x67\x78\xF6\x91\x83\xBA\x6C\x3B\xC7\x83\xDC\x7B\x8F\x06"
"\xC3\xA6\x0C\x7C\x77\x4F\xB2\x1E\x26\x54\x7D\x9D\x42\xCE\xAA\xF8\xB6\x77\x8F\x06"
"\xC3\xA7\x9F\x08\x77\x4E\xF1\xE0\xF7\x19\xDF\xD0\x67\x80\x44\xDC\x8D\x87\x21\xDD"
"\x21\xC0\x83\xB8\x69\xD4\x6B\x3A\x87\x8E\xA3\x43\xAB\x0F\x18\x7C\x1C\x74\xFB\xF0"
"\xCC\xEF\x32\xA6\x6C\xA3\xA7\x86\x05\xB4\x77\x4E\xC3\xDC\x72\x1D\x87\x78\xF0\x46"
"\x87\xCC\x3A\x78\x56\x98\xA3\xBA\x77\x8F\x1A\x60\xEE\xB1\xC7\x74\xFB\xF1\xC8\x7D"
"\x9D\xE3\xA1\x19\xD8\x42\xD9\xF0\xF8\x7D\x9F\x67\x78\xF6\x82\x55\x03\x43\xC1\xEE"
"\x1E\x04\x5C\x44\x10\xB2\x93\xEC\xEA\x3E\xCE\xF1\xE3\x3C\x7C\x3D\x86";
#define HTTP_SCRIPT_TEMPLATE Decompress(HTTP_SCRIPT_TEMPLATE_COMPRESSED,HTTP_SCRIPT_TEMPLATE_SIZE).c_str()

View File

@ -2,8 +2,8 @@ const char HTTP_SCRIPT_TEMPLATE[] PROGMEM =
"function ld(u,f){"
"var x=new XMLHttpRequest();"
"x.onreadystatechange=()=>{"
"if(this.readyState==4&&this.status==200){"
"f(this);"
"if(x.readyState==4&&x.status==200){"
"f(x);"
"}"
"};"
"x.open('GET',u,true);"

View File

@ -28,7 +28,7 @@
* Use online command StateText to translate ON, OFF, HOLD and TOGGLE.
* Use online command Prefix to translate cmnd, stat and tele.
*
* Updated until v10.1.0.6 - Last update 28.03.2022
* Updated until v10.1.0.6 - Last update 09.04.2022
\*********************************************************************/
#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English)
@ -1084,13 +1084,13 @@
#define D_NEOPOOL_RELAY_CL "Pompa cloro"
#define D_NEOPOOL_RELAY_CD "Conduttività"
#define D_NEOPOOL_RELAY_HEATING "Riscaldamento"
#define D_NEOPOOL_RELAY_UV "UV"
#define D_NEOPOOL_RELAY_VALVE "Valve"
#define D_NEOPOOL_RELAY_AUX "Aux"
#define D_NEOPOOL_RELAY_UV "Ultravioletti"
#define D_NEOPOOL_RELAY_VALVE "Valvola"
#define D_NEOPOOL_RELAY_AUX "Ausiliario"
#define D_NEOPOOL_TIME "Orario"
#define D_NEOPOOL_FILT_MODE "Modalità di filtrazione"
#define D_NEOPOOL_CELL_RUNTIME "Cella attiva"
#define D_NEOPOOL_POLARIZATION "Pol" // Sensor status
#define D_NEOPOOL_POLARIZATION "Polarizzazione" // Sensor status
#define D_NEOPOOL_PR_OFF "PrOff"
#define D_NEOPOOL_SETPOINT_OK "OK"
#define D_NEOPOOL_COVER "Copertura"

View File

@ -387,12 +387,12 @@
LV_FONT_DECLARE(robotocondensed_regular_44_latin1) \
LV_FONT_DECLARE(robotocondensed_regular_48_latin1) \
#define ROBOTOCONDENSED_REGULAR_12_LATIN1 0
#define ROBOTOCONDENSED_REGULAR_12_LATIN1 1
#define ROBOTOCONDENSED_REGULAR_14_LATIN1 0
#define ROBOTOCONDENSED_REGULAR_16_LATIN1 0
#define ROBOTOCONDENSED_REGULAR_16_LATIN1 1
#define ROBOTOCONDENSED_REGULAR_20_LATIN1 0
#define ROBOTOCONDENSED_REGULAR_22_LATIN1 0
#define ROBOTOCONDENSED_REGULAR_24_LATIN1 0
#define ROBOTOCONDENSED_REGULAR_24_LATIN1 1
#define ROBOTOCONDENSED_REGULAR_28_LATIN1 0
#define ROBOTOCONDENSED_REGULAR_32_LATIN1 0
#define ROBOTOCONDENSED_REGULAR_36_LATIN1 0

View File

@ -1034,7 +1034,7 @@
// -- LVGL Graphics Library ---------------------------------
//#define USE_LVGL // LVGL Engine, requires Berry (+382KB)
#define USE_LVGL_PSRAM // Allocate LVGL memory in PSRAM if PSRAM is connected - this might be slightly slower but leaves main memory intact
#define USE_LVGL_OPENHASP // Enable OpenHASP template compatiblity (adds LVGL template and some fonts)
// #define USE_LVGL_OPENHASP // Enable OpenHASP compatiblity and Robotocondensed fonts (+90KB flash)
#define USE_LVGL_MAX_SLEEP 10 // max sleep in ms when LVGL is enabled, more than 10ms will make display less responsive
#define USE_LVGL_PNG_DECODER // include a PNG image decoder from file system (+16KB)
//#define USE_LVGL_TOUCHSCREEN // Use virtual touch screen with Berry driver

View File

@ -486,9 +486,7 @@ typedef struct {
int32_t energy_kWhtoday_ph[3]; // 314
int32_t energy_kWhyesterday_ph[3]; // 320
int32_t energy_kWhtotal_ph[3]; // 32C
uint8_t free_338[4]; // 338
int32_t weight_user_tare; // 338
uint8_t web_time_start; // 33C
uint8_t web_time_end; // 33D
uint8_t sserial_config; // 33E
@ -647,8 +645,9 @@ typedef struct {
uint32_t ipv4_rgx_subnetmask; // 55C
uint16_t pwm_value_ext[16-5]; // 560 Extension to pwm_value to store up to 16 PWM for ESP32. This array stores values 5..15
uint8_t free_576[6]; // 576
uint8_t free_576[2]; // 576
int32_t weight_offset; // 578
uint16_t pulse_timer[MAX_PULSETIMERS]; // 57C
SysMBitfield1 flag2; // 5BC
uint32_t pulse_counter[MAX_COUNTERS]; // 5C0

View File

@ -1520,6 +1520,13 @@ void SettingsDelta(void) {
Settings->weight_absconv_a = 0;
Settings->weight_absconv_b = 0;
}
if (Settings->version < 0x0B000007) { // 11.0.0.7
Settings->weight_user_tare = 0;
Settings->weight_offset = 0;
#ifdef USE_HX711
Settings->weight_offset = Settings->energy_frequency_calibration * Settings->weight_calibration;
#endif
}
Settings->version = VERSION;
SettingsSave(1);

View File

@ -3164,14 +3164,23 @@ int WebQuery(char *buffer)
// Return received data to the user - Adds 900+ bytes to the code
const char* read = http.getString().c_str(); // File found at server - may need lot of ram or trigger out of memory!
ResponseClear();
Response_P(PSTR("{\"" D_CMND_WEBQUERY "\":"));
char text[2] = { 0 };
text[0] = '.';
text[0] = *read++;
bool assume_json = (text[0] == '{') || (text[0] == '[');
if (!assume_json) { ResponseAppend_P(PSTR("\"")); }
while (text[0] != '\0') {
text[0] = *read++;
if (text[0] > 31) { // Remove control characters like linefeed
if (ResponseAppend_P(text) == ResponseSize()) { break; };
if (assume_json) {
if (ResponseAppend_P(text) == ResponseSize()) { break; };
} else {
if (ResponseAppend_P(EscapeJSONString(text).c_str()) == ResponseSize()) { break; };
}
}
text[0] = *read++;
}
if (!assume_json) { ResponseAppend_P(PSTR("\"")); }
ResponseJsonEnd();
#ifdef USE_SCRIPT
extern uint8_t tasm_cmd_activ;
// recursive call must be possible in this case

View File

@ -10321,7 +10321,7 @@ bool Xdrv10(uint8_t function)
Webserver->on("/ta",HTTP_POST, HandleScriptTextareaConfiguration);
Webserver->on("/exs", HTTP_POST,[]() { Webserver->sendHeader("Location","/exs");Webserver->send(303);}, script_upload_start);
Webserver->on("/exs", HTTP_GET, ScriptExecuteUploadSuccess);
#ifdef USE_UFILESYS
#if defined(USE_UFILESYS) && defined(USE_SCRIPT_WEB_DISPLAY)
Webserver->on(UriGlob("/ufs/*"), HTTP_GET, ScriptServeFile);
#endif
#endif // USE_WEBSERVER

View File

@ -387,6 +387,10 @@ void MESHstartNode(int32_t _channel, uint8_t _role){ //we need a running broker
MESHsetWifi(0);
if (esp_now_init() != 0) {
AddLog(LOG_LEVEL_INFO, PSTR("MSH: Node init failed"));
// try to re-launch wifi
MESH.role = ROLE_NONE;
MESHsetWifi(1);
WifiBegin(3, MESH.channel);
return;
}

View File

@ -18,6 +18,7 @@
*/
#ifdef ESP32
#ifndef CONFIG_IDF_TARGET_ESP32S3
/*********************************************************************************************\
* ESP32 CPU Temperature and optional Hall Effect sensor
*
@ -138,4 +139,5 @@ bool Xsns127(uint8_t function) {
return result;
}
#endif // Not CONFIG_IDF_TARGET_ESP32S3
#endif // ESP32

View File

@ -53,12 +53,14 @@
#define HX_GAIN_64 3 // Channel A, gain factor 64
#define D_JSON_WEIGHT_RAW "WeightRaw"
#define D_JSON_WEIGHT_RAW_ABS "AbsRaw"
#define D_JSON_WEIGHT_REF "Ref"
#define D_JSON_WEIGHT_CAL "Cal"
#define D_JSON_WEIGHT_MAX "Max"
#define D_JSON_WEIGHT_ITEM "Item"
#define D_JSON_WEIGHT_CHANGE "Change"
#define D_JSON_WEIGHT_DELTA "Delta"
#define D_JSON_WEIGHT_TARE "Tare"
#define D_JSON_WEIGHT_ABSC_A "AbsConvA"
#define D_JSON_WEIGHT_ABSC_B "AbsConvB"
@ -68,8 +70,10 @@ const char kHxCalibrationStates[] PROGMEM = D_HX_CAL_FAIL "|" D_HX_CAL_DONE "|"
struct HX {
long reads[HX_SAMPLES];
long weight = 0;
long raw_empty = 0;
long raw_absolute;
long raw = 0;
long weight = 0;
long last_weight = 0;
long offset = 0;
long scale = 1;
@ -134,15 +138,11 @@ long HxRead(void) {
/*********************************************************************************************/
void HxResetPart(void) {
Hx.tare_flg = true;
Hx.sample_count = 0;
Hx.last_weight = 0;
}
void HxReset(void) {
HxResetPart();
Settings->energy_frequency_calibration = 0;
void HxTareInit(void) {
Hx.offset = (Settings->weight_user_tare != 0) ? Settings->weight_user_tare * Hx.scale : Settings->weight_offset;
if (0 == Hx.offset) {
Hx.tare_flg = true;
}
}
void HxCalibrationStateTextJson(uint8_t msg_id) {
@ -174,23 +174,24 @@ void SetWeightDelta(void) {
/*********************************************************************************************\
* Supported commands for Sensor34:
*
* Sensor34 - Show current settings
* Sensor34 1 - Reset display to 0
* Sensor34 2 - Start calibration
* Sensor34 2 <weight in gram> - Set reference weight and start calibration
* Sensor34 3 - Show reference weight in gram
* Sensor34 3 <weight in gram> - Set reference weight
* Sensor34 4 - Show calibrated scale value
* Sensor34 4 <scale value> - Set calibrated scale value
* Sensor34 5 - Show max weight in gram
* Sensor34 5 <weight in gram> - Set max weight
* Sensor34 6 - Show item weight in decigram
* Sensor34 6 <weight in decigram> - Set item weight
* Sensor34 7 - Save current weight to be used as start weight on restart
* Sensor34 7 - Save current weight to be used as start weight on restart (removed v11.0.0.7)
* Sensor34 8 0 - Disable JSON weight change message
* Sensor34 8 1 - Enable JSON weight change message
* Sensor34 9 <weight code> - Set minimum delta to trigger JSON message
* Sensor34 10 <value A> - Set A = a * 10^9 for raw to absolute weight conversion: y=a*x+b
* Sensor34 11 <value B> - Set B = b * 10^6 for raw to absolute weight conversion: y=a*x+b
* Sensor34 10 0 - Disable fixed tare and enable auto tare
* Sensor34 10 1 - Set fixed tare offset using current calibrated raw weight value
* Sensor34 10 <weight in gram> - Set fixed tare offset
* Sensor34 11 0 - Disable absolute weight conversion
* Sensor34 11 <value A> - Set A = a * 10^9 for raw to absolute weight conversion: y=a*x+b
* Sensor34 12 <value B> - Set B = b * 10^6 for raw to absolute weight conversion: y=a*x+b
\*********************************************************************************************/
bool HxCommand(void) {
@ -207,17 +208,21 @@ bool HxCommand(void) {
switch (XdrvMailbox.payload) {
case 1: // Reset scale
HxReset();
Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_34, "Reset");
if (0 == Settings->weight_user_tare) {
Hx.tare_flg = true;
Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_34, "Reset");
}
show_parms = false;
break;
case 2: // Calibrate
if (any_value) { Settings->weight_reference = value; }
Hx.scale = 1;
HxReset();
Hx.scale = 1; // Uncalibrated
Hx.sample_count = 0;
Hx.offset = 0; // Disable tare while calibrating
Hx.calibrate_step = HX_CAL_START;
Hx.calibrate_timer = 1;
HxCalibrationStateTextJson(3);
// HxCalibrationStateTextJson(3); // D_HX_CAL_REMOVE
HxCalibrationStateTextJson(2); // D_HX_CAL_REMOVE
show_parms = false;
break;
case 3: // WeightRef to user reference
@ -237,11 +242,11 @@ bool HxCommand(void) {
Settings->weight_item = (unsigned long)(CharToFloat(ArgV(argument, 2)) * 10);
}
break;
case 7: // WeightSave
Settings->energy_frequency_calibration = Hx.weight;
Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_34, PSTR(D_JSON_DONE));
show_parms = false;
break;
// case 7: // WeightSave
// Settings->energy_frequency_calibration = Hx.weight;
// Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_34, PSTR(D_JSON_DONE));
// show_parms = false;
// break;
case 8: // Json on weight change
if (any_value) { Settings->SensorBits1.hx711_json_weight_change = value &1; }
break;
@ -251,10 +256,17 @@ bool HxCommand(void) {
SetWeightDelta();
}
break;
case 10: // AbsoluteConversion, A
case 10: // Fixed (user) tare
if (any_value) {
Settings->weight_user_tare = (1 == value) ? Hx.raw : value;
HxTareInit();
Hx.weight_diff = Hx.weight_delta +1; // Force display of current weight
}
break;
case 11: // AbsoluteConversion, A
if (any_value) { Settings->weight_absconv_a = value; }
break;
case 11: // AbsoluteConversion, B
case 12: // AbsoluteConversion, B
if (any_value) { Settings->weight_absconv_b = value; }
break;
}
@ -264,10 +276,10 @@ bool HxCommand(void) {
dtostrfd((float)Settings->weight_item / 10, 1, item);
Response_P(PSTR("{\"Sensor34\":{\"" D_JSON_WEIGHT_REF "\":%d,\"" D_JSON_WEIGHT_CAL "\":%d,\"" D_JSON_WEIGHT_MAX "\":%d,\""
D_JSON_WEIGHT_ITEM "\":%s,\"" D_JSON_WEIGHT_CHANGE "\":\"%s\",\"" D_JSON_WEIGHT_DELTA "\":%d,\""
D_JSON_WEIGHT_ABSC_A "\":%d,\"" D_JSON_WEIGHT_ABSC_B "\":%d}}"),
D_JSON_WEIGHT_TARE "\":%d,\"" D_JSON_WEIGHT_ABSC_A "\":%d,\"" D_JSON_WEIGHT_ABSC_B "\":%d}}"),
Settings->weight_reference, Settings->weight_calibration, Settings->weight_max * 1000,
item, GetStateText(Settings->SensorBits1.hx711_json_weight_change), Settings->weight_change,
Settings->weight_absconv_a, Settings->weight_absconv_b);
Settings->weight_user_tare, Settings->weight_absconv_a, Settings->weight_absconv_b);
}
return serviced;
@ -297,8 +309,8 @@ void HxInit(void) {
if (!Settings->weight_calibration) { Settings->weight_calibration = HX_SCALE; }
if (!Settings->weight_reference) { Settings->weight_reference = HX_REFERENCE; }
Hx.scale = Settings->weight_calibration;
HxTareInit();
HxRead();
HxResetPart();
Hx.type = 1;
}
}
@ -328,45 +340,44 @@ void HxEvery100mSecond(void) {
for (uint32_t i = 2; i < HX_SAMPLES -2; i++) {
sum_raw += Hx.reads[i];
}
long average = sum_raw / (HX_SAMPLES -4); // grams
Hx.raw_absolute = sum_raw / (HX_SAMPLES -4); // Uncalibrated value
Hx.raw = Hx.raw_absolute / Hx.scale; // grams
if ((Hx.reads[0] < (average -4)) || (Hx.reads[9] > (average +4))) {
AddLog(LOG_LEVEL_DEBUG, PSTR("HX7: Range %d"), Hx.reads[9] - Hx.reads[0]);
// return; // Consider to drop samples with too much deviation (will fail too on quick load changes like filling a barrel!)
}
long value = average - Hx.offset; // grams
Hx.weight = value / Hx.scale; // grams
Hx.raw = average / Hx.scale;
if (Hx.weight < 0) {
if (Settings->energy_frequency_calibration) {
long difference = Settings->energy_frequency_calibration + Hx.weight;
Hx.last_weight = difference;
if (difference < 0) { HxReset(); } // Cancel last weight as there seems to be no more weight on the scale
}
Hx.weight = 0;
} else {
Hx.last_weight = Settings->energy_frequency_calibration;
}
if (Hx.tare_flg) {
if ((0 == Settings->weight_user_tare) && Hx.tare_flg) { // Reset scale based on current load
Hx.tare_flg = false;
Hx.offset = average; // grams
Settings->weight_offset = Hx.raw_absolute; // Save for restart use
Hx.offset = Hx.raw_absolute;
}
long value = Hx.raw_absolute - Hx.offset; // Uncalibrated value
Hx.weight = value / Hx.scale; // grams
if (Hx.weight < 0) { // We currently do not support negative weight
Hx.weight = 0;
}
if (Hx.calibrate_step) {
Hx.calibrate_timer--;
// AddLog(LOG_LEVEL_DEBUG, PSTR("HX7: Step %d, weight %d, last %d, raw %d, empty %d"), Hx.calibrate_step, Hx.weight, Hx.last_weight, Hx.raw, Hx.raw_empty);
if (HX_CAL_START == Hx.calibrate_step) { // Skip reset just initiated
Hx.calibrate_step--;
if (0 == Hx.offset) {
Hx.calibrate_step--; // HX_CAL_RESET
Hx.last_weight = Hx.weight; // Uncalibrated value
Hx.raw_empty = Hx.raw;
}
Hx.calibrate_timer = HX_CAL_TIMEOUT * (10 / HX_SAMPLES);
}
else if (HX_CAL_RESET == Hx.calibrate_step) { // Wait for stable reset
if (Hx.calibrate_timer) {
if (Hx.weight < (long)Settings->weight_reference) {
Hx.calibrate_step--;
if (Hx.weight < Hx.last_weight -100) { // Load decrease detected
Hx.last_weight = Hx.weight;
Hx.raw_empty = Hx.raw;
// HxCalibrationStateTextJson(2); // D_HX_CAL_REFERENCE
}
else if (Hx.weight > Hx.last_weight +100) { // Load increase detected
Hx.calibrate_step--; // HX_CAL_FIRST
Hx.calibrate_timer = HX_CAL_TIMEOUT * (10 / HX_SAMPLES);
HxCalibrationStateTextJson(2);
}
} else {
Hx.calibrate_step = HX_CAL_FAIL;
@ -374,41 +385,46 @@ void HxEvery100mSecond(void) {
}
else if (HX_CAL_FIRST == Hx.calibrate_step) { // Wait for first reference weight
if (Hx.calibrate_timer) {
if (Hx.weight > (long)Settings->weight_reference) {
Hx.calibrate_step--;
if (Hx.weight > Hx.last_weight +100) {
Hx.calibrate_step--; // HX_CAL_DONE
}
} else {
Hx.calibrate_step = HX_CAL_FAIL;
}
}
else if (HX_CAL_DONE == Hx.calibrate_step) { // Second stable reference weight
if (Hx.weight > (long)Settings->weight_reference) {
if (Hx.weight > Hx.last_weight +100) {
Hx.calibrate_step = HX_CAL_FINISH; // Calibration done
Settings->weight_calibration = Hx.weight / Settings->weight_reference;
Settings->weight_offset = Hx.raw_empty;
Hx.offset = Hx.raw_empty;
Settings->weight_calibration = (Hx.weight - Hx.raw_empty) / Settings->weight_reference; // 1 gram
Hx.weight = 0; // Reset calibration value
HxCalibrationStateTextJson(1);
HxCalibrationStateTextJson(1); // D_HX_CAL_DONE
} else {
Hx.calibrate_step = HX_CAL_FAIL;
}
}
if (HX_CAL_FAIL == Hx.calibrate_step) { // Calibration failed
Hx.calibrate_step--;
Hx.tare_flg = true; // Perform a reset using old scale
HxCalibrationStateTextJson(0);
Hx.calibrate_step--; // HX_CAL_FINISH
HxTareInit();
HxCalibrationStateTextJson(0); // D_HX_CAL_FAIL
}
if (HX_CAL_FINISH == Hx.calibrate_step) { // Calibration finished
Hx.calibrate_step--;
Hx.calibrate_step--; // HX_CAL_LIMBO
Hx.calibrate_timer = 3 * (10 / HX_SAMPLES);
Hx.scale = Settings->weight_calibration;
}
if (Settings->weight_user_tare != 0) { // Re-enable fixed tare if needed
Settings->weight_user_tare = Hx.raw_empty / Hx.scale;
HxTareInit();
}
}
if (!Hx.calibrate_timer) {
Hx.calibrate_step = HX_CAL_END; // End of calibration
Hx.weight_diff = Hx.weight_delta +2;
}
} else {
Hx.weight += Hx.last_weight; // grams
if (Settings->SensorBits1.hx711_json_weight_change) {
if (abs(Hx.weight - Hx.weight_diff) > Hx.weight_delta) { // Use weight_delta threshold to decrease "ghost" weights
Hx.weight_diff = Hx.weight;
@ -428,7 +444,6 @@ void HxEvery100mSecond(void) {
}
void HxSaveBeforeRestart(void) {
Settings->energy_frequency_calibration = Hx.weight;
Hx.sample_count = HX_SAMPLES +1; // Stop updating Hx.weight
}
@ -448,8 +463,9 @@ void HxShow(bool json) {
float weight = 0;
if (Hx.calibrate_step < HX_CAL_FAIL) {
if ((Settings->weight_absconv_a != 0) && (Settings->weight_absconv_b != 0)) {
weight = (float)Settings->weight_absconv_a / 1e9 * Hx.raw + (float)Settings->weight_absconv_b / 1e6;
} else {
weight = (float)Settings->weight_absconv_a / 1e9 * Hx.raw_absolute + (float)Settings->weight_absconv_b / 1e6;
}
else {
if (Hx.weight && Settings->weight_item) {
count = (Hx.weight * 10) / Settings->weight_item;
if (count > 1) {
@ -463,7 +479,8 @@ void HxShow(bool json) {
dtostrfd(weight, Settings->flag2.weight_resolution, weight_chr);
if (json) {
ResponseAppend_P(PSTR(",\"HX711\":{\"" D_JSON_WEIGHT "\":%s%s,\"" D_JSON_WEIGHT_RAW "\":%d}"), weight_chr, scount, Hx.raw);
ResponseAppend_P(PSTR(",\"HX711\":{\"" D_JSON_WEIGHT "\":%s%s,\"" D_JSON_WEIGHT_RAW "\":%d,\"" D_JSON_WEIGHT_RAW_ABS "\":%d}"),
weight_chr, scount, Hx.raw, Hx.raw_absolute);
#ifdef USE_WEBSERVER
} else {
WSContentSend_PD(HTTP_HX711_WEIGHT, weight_chr);
@ -582,7 +599,9 @@ bool Xsns34(uint8_t function) {
break;
#ifdef USE_HX711_GUI
case FUNC_WEB_ADD_MAIN_BUTTON:
WSContentSend_P(HTTP_BTN_MENU_MAIN_HX711);
if (0 == Settings->weight_user_tare) { // Allow reset scale when no user tare is defined
WSContentSend_P(HTTP_BTN_MENU_MAIN_HX711);
}
break;
case FUNC_WEB_ADD_BUTTON:
WSContentSend_P(HTTP_BTN_MENU_HX711);

View File

@ -666,7 +666,7 @@ extern "C" {
MI32.conCtx->operation = operation%10;
MI32.conCtx->response = response;
AddLog(LOG_LEVEL_DEBUG,PSTR("M32: Berry connection op: %d, addrType: %d, oneOp: %u, response: %u"),MI32.conCtx->operation, MI32.conCtx->addrType, MI32.conCtx->oneOp, MI32.conCtx->response);
if(MI32.conCtx->oneOp || MI32.conCtx->operation == 5){ //...or disconnect is requested
if(MI32.conCtx->oneOp){
MI32StartConnectionTask();
}
else{
@ -1087,6 +1087,9 @@ void MI32ScanTask(void *pvParameters){
}
bool MI32ConnectActiveSensor(){ // only use inside a task !!
if(MI32.conCtx->operation == 5) {
return false;
}
NimBLEAddress _address = NimBLEAddress(MI32.conCtx->MAC, MI32.conCtx->addrType);
if(MI32Client != nullptr){
if(MI32Client->isConnected() && MI32.mode.connected == 1){ //we only accept a "clean" state without obvious packet losses
@ -1114,7 +1117,6 @@ bool MI32ConnectActiveSensor(){ // only use inside a task !!
MI32Client->setClientCallbacks(&MI32SensorCB , false);
}
if (!MI32Client->connect(false)) {
MI32.mode.willConnect = 0;
NimBLEDevice::deleteClient(MI32Client);
// AddLog(LOG_LEVEL_ERROR,PSTR("M32: did not connect client"));
return false;
@ -1140,8 +1142,10 @@ bool MI32StartConnectionTask(){
}
void MI32ConnectionTask(void *pvParameters){
#if !defined(CONFIG_IDF_TARGET_ESP32C3) //needs more testing ...
NimBLEDevice::setOwnAddrType(BLE_OWN_ADDR_RANDOM,false); //seems to be important for i.e. xbox controller, hopefully not breaking other things
NimBLEDevice::setSecurityAuth(true, true, true);
#endif //CONFIG_IDF_TARGET_ESP32C3
MI32.conCtx->error = MI32_CONN_NO_ERROR;
if (MI32ConnectActiveSensor()){
MI32.mode.readingDone = 0;
@ -1176,9 +1180,13 @@ void MI32ConnectionTask(void *pvParameters){
}
// AddLog(LOG_LEVEL_INFO,PSTR("M32: wait ..."));
}
// AddLog(LOG_LEVEL_INFO,PSTR("M32: really start connection job now ..."));
MI32.mode.triggerNextConnJob = 0;
MI32.mode.readyForNextConnJob = 0;
if(MI32.conCtx->operation == 5){
MI32Client->disconnect();
break;
}
pSvc = MI32Client->getService(MI32.conCtx->serviceUUID);
if(pSvc) {
pChr = pSvc->getCharacteristic(MI32.conCtx->charUUID);
@ -1199,9 +1207,9 @@ void MI32ConnectionTask(void *pvParameters){
}
break;
case 2:
if(pChr->canWrite()) {
if(pChr->canWrite() || pChr->canWriteNoResponse()) {
uint8_t len = MI32.conCtx->buffer[0];
if(pChr->writeValue(MI32.conCtx->buffer + 1,len,MI32.conCtx->response)) { // true is important !
if(pChr->writeValue(MI32.conCtx->buffer + 1,len,MI32.conCtx->response & !pChr->canWriteNoResponse())) { // falls always back to "no response" if server provides both options
// AddLog(LOG_LEVEL_DEBUG,PSTR("M32: write op done"));
}
else{
@ -1228,28 +1236,28 @@ void MI32ConnectionTask(void *pvParameters){
}
}
else{
MI32.conCtx->error = MI32_CONN_NO_CHARACTERISTIC;
MI32.conCtx->error = MI32_CONN_NO_CHARACTERISTIC;
}
timer = 0;
while (timer<150){
if (MI32.mode.readingDone || !MI32.conCtx->oneOp){
break;
}
else{
if (MI32.conCtx->operation==3 && MI32.conCtx->oneOp) {
MI32.conCtx->error = MI32_CONN_NOTIFY_TIMEOUT; //did not read on notify - timeout only for one-shot op
if(MI32.conCtx->error == MI32_CONN_NO_ERROR){
while (timer<150){
if (MI32.mode.readingDone || !MI32.conCtx->oneOp){
break;
}
else if (timer>148){
if (MI32.conCtx->operation==3 && MI32.conCtx->oneOp) {
MI32.conCtx->error = MI32_CONN_NOTIFY_TIMEOUT; //did not read on notify - timeout only for one-shot op
}
}
timer++;
vTaskDelay(100/ portTICK_PERIOD_MS);
}
}
timer++;
vTaskDelay(100/ portTICK_PERIOD_MS);
}
MI32.mode.readingDone = 0;
if(MI32.conCtx->oneOp){
MI32Client->disconnect();
MI32.mode.connected = 0;
keepConnectionAlive = false;
MI32StartTask(MI32_TASK_SCAN);
}
else{
MI32.mode.readyForNextConnJob = 1;
@ -1258,15 +1266,10 @@ void MI32ConnectionTask(void *pvParameters){
}
}
else{
if(MI32.conCtx->operation==5){
MI32.conCtx->error = MI32_CONN_DID_DISCCONNECT; // did succesfully disconnect
}
else{
MI32.conCtx->error = MI32_CONN_NO_CONNECT; // could not connect
}
MI32.mode.connected = 0;
MI32StartTask(MI32_TASK_SCAN);
MI32.mode.willConnect = 0;
MI32.conCtx->error = MI32_CONN_NO_CONNECT; // could not connect (including op:5 in not connected state)
}
MI32.mode.connected = 0;
MI32.mode.triggerBerryConnCB = 1;
MI32StartTask(MI32_TASK_SCAN);
vTaskDelete( NULL );
@ -1660,9 +1663,9 @@ void MI32Every50mSecond(){
void (*func_ptr)(int, int, int) = (void (*)(int, int, int))MI32.beConnCB;
char _message[32];
GetTextIndexed(_message, sizeof(_message), MI32.conCtx->error, kMI32_ConnErrorMsg);
AddLog(LOG_LEVEL_DEBUG,PSTR("M32: %s"),_message);
AddLog(LOG_LEVEL_DEBUG,PSTR("M32: BryCbMsg: %s"),_message);
func_ptr(MI32.conCtx->error, MI32.conCtx->operation , MI32.conCtx->returnCharUUID);
}
}
MI32.mode.triggerBerryConnCB = 0;
}
if(MI32.infoMsg > 0){

View File

@ -363,6 +363,8 @@ enum NeoPoolConstAndBitMask {
MBMSK_RELAY_FILTSPEED_LOW = 0x0100, // 8 Filtration low speed
MBMSK_RELAY_FILTSPEED_MID = 0x0200, // 9 Filtration mid speed
MBMSK_RELAY_FILTSPEED_HIGH = 0x0400, // 10 Filtration high speed
MBMSK_RELAY_FILTSPEED = 0x0700, // Filtration current speed mask
MBSHFT_RELAY_FILTSPEED = 8, // Filtration current speed bit shift
// MBF_NOTIFICATION
MBMSK_NOTIF_MODBUS_CHANGED = 0x0001, // 0 Modbus page changed
@ -1298,7 +1300,7 @@ uint8_t NeoPoolWriteRegisterWord(uint16_t addr, uint16_t data)
}
uint16_t NeoPoolGetDataTO(uint16_t addr, uint32_t timeout)
uint16_t NeoPoolGetDataTO(uint16_t addr, int32_t timeout)
{
uint16_t data;
uint16_t i;
@ -1355,16 +1357,23 @@ uint32_t NeoPoolGetDataLong(uint16_t addr)
}
uint32_t NeoPoolGetSpeedIndex(uint16_t speedvalue)
uint32_t NeoPoolGetFiltrationSpeed()
{
if (speedvalue >= 4) {
return 3;
switch((NeoPoolGetData(MBF_RELAY_STATE) & MBMSK_RELAY_FILTSPEED) >> MBSHFT_RELAY_FILTSPEED) {
case 1:
return 1;
case 2:
return 2;
case 4:
return 3;
}
if (speedvalue >= 2) {
return 2;
}
if (speedvalue >= 1) {
return 1;
switch((NeoPoolGetData(MBF_PAR_FILTRATION_CONF) & MBMSK_PAR_FILTRATION_CONF_DEF_SPEED) >> MBSHFT_PAR_FILTRATION_CONF_DEF_SPEED) {
case MBV_PAR_FILTRATION_SPEED_SLOW:
return 1;
case MBV_PAR_FILTRATION_SPEED_MEDIUM:
return 2;
case MBV_PAR_FILTRATION_SPEED_FAST:
return 3;
}
return 0;
}
@ -1642,7 +1651,7 @@ void NeoPoolShow(bool json)
if (0 != NeoPoolGetData(MBF_PAR_FILT_GPIO)) {
ResponseAppend_P(PSTR(",\"" D_NEOPOOL_JSON_FILTRATION "\":"));
ResponseAppend_P(PSTR("{\"" D_NEOPOOL_JSON_STATE "\":%d"), (NeoPoolGetData(MBF_RELAY_STATE) >> (NeoPoolGetData(MBF_PAR_FILT_GPIO)-1)) & 1);
uint16_t speed = (NeoPoolGetData(MBF_RELAY_STATE) >> 8) & 0x07;
uint16_t speed = NeoPoolGetFiltrationSpeed();
if (speed) {
ResponseAppend_P(PSTR(",\"" D_NEOPOOL_JSON_FILTRATION_SPEED "\":%d"), (speed < 3) ? speed : 3);
}
@ -1879,7 +1888,7 @@ void NeoPoolShow(bool json)
} else if (0 != NeoPoolGetData(MBF_PAR_FILT_GPIO) && i == NeoPoolGetData(MBF_PAR_FILT_GPIO)-1) {
char smotorspeed[32];
strncpy_P(sdesc, PSTR(D_NEOPOOL_RELAY_FILTRATION), sizeof(sdesc));
GetTextIndexed(smotorspeed, sizeof(smotorspeed), NeoPoolGetSpeedIndex((NeoPoolGetData(MBF_RELAY_STATE) >> 8) & 0x7), kNeoPoolFiltrationSpeed);
GetTextIndexed(smotorspeed, sizeof(smotorspeed), NeoPoolGetFiltrationSpeed(), kNeoPoolFiltrationSpeed);
snprintf_P(stemp, sizeof(stemp), PSTR("%s%s%s%s"), ((NeoPoolGetData(MBF_RELAY_STATE) & (1<<i))?D_ON:D_OFF), *smotorspeed ? PSTR(" (") : PSTR(""), smotorspeed, *smotorspeed ? PSTR(")") : PSTR(""));
} else if (0 != NeoPoolGetData(MBF_PAR_LIGHTING_GPIO) && i == NeoPoolGetData(MBF_PAR_LIGHTING_GPIO)-1) {
strncpy_P(sdesc, PSTR(D_NEOPOOL_RELAY_LIGHT), sizeof(sdesc));
@ -2140,7 +2149,7 @@ void CmndNeopoolFiltration(void)
NeopoolResponseError();
return;
}
uint16_t speed = (NeoPoolGetData(MBF_RELAY_STATE) >> 8) & 0x07;
uint16_t speed = NeoPoolGetFiltrationSpeed();
if (speed) {
Response_P(PSTR("{\"%s\":\"%s\",\"" D_NEOPOOL_JSON_FILTRATION_SPEED "\":\"%d\"}"),
XdrvMailbox.command,

View File

@ -370,12 +370,12 @@ void MCP2515_Show(bool Json) {
if (bms.setFields & BMS_CHARGE_VOLT_MAX) {
char voltStr[6];
dtostrf((float(bms.chargeVoltLimit) / 10), 5, 1, voltStr);
WSContentSend_PD(PSTR("{s}%s Max Voltage{m}%s " D_UNIT_AMPERE "{e}"), bms.manuf, voltStr);
WSContentSend_PD(PSTR("{s}%s Max Voltage{m}%s " D_UNIT_VOLT "{e}"), bms.manuf, voltStr);
}
if (bms.setFields & BMS_CHARGE_VOLT_MIN) {
char voltStr[6];
dtostrf((float(bms.dischargeVolt) / 10), 5, 1, voltStr);
WSContentSend_PD(PSTR("{s}%s Min Voltage{m}%s " D_UNIT_AMPERE "{e}"), bms.manuf, voltStr);
WSContentSend_PD(PSTR("{s}%s Min Voltage{m}%s " D_UNIT_VOLT "{e}"), bms.manuf, voltStr);
}
if (bms.setFields & BMS_CHARGE_AMP_MAX) {
char ampStr[6];