Zigbee add default plugin in flash

This commit is contained in:
Stephan Hadinger 2022-11-18 00:21:01 +01:00
parent 24126efc4d
commit 7e9e7b8e3e
4 changed files with 391 additions and 201 deletions

View File

@ -761,17 +761,6 @@ void ZCLFrame::computeSyntheticAttributes(Z_attribute_list& attr_list) {
attr_list.addAttribute(0x0001, 0x0021).setUInt(toPercentageCR2032(mv) * 2);
}
break;
case 0x00010021: // BatteryPercentage
if (modelId.startsWith(F("TRADFRI")) ||
modelId.startsWith(F("SYMFONISK"))) {
attr.setUInt(attr.getUInt() * 2); // bug in IKEA remotes battery, need to double the value
}
break;
case 0x00060000: // "Power" for lumi Door/Window is converted to "Contact"
if (modelId.startsWith(F("lumi.sensor_magnet"))) {
attr.setKeyId(0x0500, 0xFFF0 + ZA_Contact); // change cluster and attribute to 0500/FFF0
}
break;
case 0x02010008: // Pi Heating Demand - solve Eutotronic bug
case 0x02014008: // Eurotronic Host Flags decoding
{

View File

@ -0,0 +1,142 @@
/*
xdrv_23_zigbee_7_6_flash_fs.ino - implement a Flash based read-only triviall file-system
Copyright (C) 2022 Theo Arends and Stephan Hadinger
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef USE_ZIGBEE
#ifdef ESP32
#include <vfs_api.h>
#else
#include "FSImpl.h"
#endif
/********************************************************************
** Subfile implementation
**
** Takes a string point in Flash and turn it to a read-only file
********************************************************************/
class FlashFileImpl;
typedef std::shared_ptr<FlashFileImpl> FlashFileImplPtr;
class FlashFileImpl : public FileImpl {
public:
FlashFileImpl(const char* str) {
_buf = str;
_len = strlen_P(str);
_seek = 0;
}
virtual ~FlashFileImpl() {}
size_t write(const uint8_t *buf, size_t size) {
return 0; // not accepted
}
size_t read(uint8_t* buf, size_t size) {
if (_seek < _len) {
if (size + _seek > _len) {
size = _len - _seek; // always > 0 because of guarding test
}
memcpy_P(buf, _buf + _seek, size);
_seek += size;
return size;
}
return 0; // abort
}
void flush() {
// do nothing
}
bool setBufferSize(size_t size) {
return true;
}
bool seek(uint32_t pos, SeekMode mode) {
// AddLog(LOG_LEVEL_DEBUG, "ZIP: seek pos=%i mode=%i", pos, mode);
if (SeekSet == mode) {
if (pos <= _len) {
_seek = pos;
return true;
}
} else if (SeekCur == mode) {
if (_seek + pos <= _len) {
_seek += pos;
return true;
}
} else if (SeekEnd == mode) {
_seek = _len;
return true;
}
return false;
}
size_t position() const {
return _seek;
}
size_t size() const {
return _len;
}
void close() {
// do nothing
}
time_t getLastWrite() {
return 0;
}
const char* path() const {
return "";
}
const char* name() const {
return "<internal>";
}
boolean isDirectory(void) {
return false; // no directory allowed
}
FileImplPtr openNextFile(const char* mode) {
return nullptr; // TODO
}
void rewindDirectory(void) {
// ignore
}
operator bool() {
return true;
}
// ESP8266 specific?
bool truncate(uint32_t size) { return false; }
const char* fullName() const { return ""; }
bool isFile() const { return true; }
bool isDirectory() const { return false; }
protected:
const char * _buf;
size_t _len;
uint32_t _seek;
};
#endif // USE_ZIGBEE

View File

@ -125,28 +125,7 @@ bool Zb_readline(class File *f, char* buf, size_t size) {
extern FS *ffsp;
#endif
// load a file from filesystem
// returns `true` if success
bool ZbLoad(const char *filename_raw) {
#ifdef USE_UFILESYS
if (ffsp) {
// first unload previsou definitions
ZbUnload(filename_raw);
String filename = filename_raw;
if (filename_raw[0] != '/') {
filename = "/";
filename += filename_raw;
}
File fp;
fp = ffsp->open(filename.c_str(), "r");
if (fp <= 0) {
AddLog(LOG_LEVEL_INFO, "ZIG: unable to load file '%s'", filename.c_str());
return false;
}
bool ZbLoad_inner(const char *filename, File &fp) {
char * filename_imported = nullptr;
Z_plugin_template * tmpl = nullptr; // current template with matchers and attributes
bool new_matchers = false; // indicates that we have finished the current matchers
@ -171,7 +150,7 @@ bool ZbLoad(const char *filename_raw) {
}
if (invalid_header) {
AddLog(LOG_LEVEL_INFO, "ZIG: ZbLoad '%s' invalid header", filename_raw);
AddLog(LOG_LEVEL_INFO, "ZIG: ZbLoad '%s' invalid header", filename);
return false;
}
@ -186,8 +165,8 @@ bool ZbLoad(const char *filename_raw) {
if (filename_imported == nullptr) {
// allocate only once the filename for multiple entries
// freed only by `ZbUnload`
filename_imported = (char*) malloc(strlen(filename.c_str())+1);
strcpy(filename_imported, filename.c_str());
filename_imported = (char*) malloc(strlen(filename)+1);
strcpy(filename_imported, filename);
}
// there is a non-empty line, containing no space/tab/crlf
@ -229,7 +208,7 @@ bool ZbLoad(const char *filename_raw) {
char * delimiter_slash = strchr(token, '/');
char * delimiter_percent = strchr(token, '%');
if (delimiter_slash == nullptr || (delimiter_percent != nullptr && delimiter_slash > delimiter_percent)) {
AddLog(LOG_LEVEL_INFO, "ZIG: ZbLoad '%s' wrong delimiter '%s'", filename_raw, token);
AddLog(LOG_LEVEL_INFO, "ZIG: ZbLoad '%s' wrong delimiter '%s'", filename, token);
}
uint16_t attr_id = 0xFFFF;
@ -251,7 +230,7 @@ bool ZbLoad(const char *filename_raw) {
// NAME of the attribute
token = strtok_r(rest, ",", &rest);
if (token == nullptr) {
AddLog(LOG_LEVEL_INFO, "ZIG: ZbLoad '%s' ignore missing name '%s'", filename_raw, buf_line);
AddLog(LOG_LEVEL_INFO, "ZIG: ZbLoad '%s' ignore missing name '%s'", filename, buf_line);
continue;
}
name = token;
@ -337,6 +316,32 @@ bool ZbLoad(const char *filename_raw) {
}
}
}
return true;
}
// load a file from filesystem
// returns `true` if success
bool ZbLoad(const char *filename_raw) {
#ifdef USE_UFILESYS
if (ffsp) {
// first unload previsou definitions
ZbUnload(filename_raw);
String filename = filename_raw;
if (filename_raw[0] != '/') {
filename = "/";
filename += filename_raw;
}
File fp;
fp = ffsp->open(filename.c_str(), "r");
if (fp <= 0) {
AddLog(LOG_LEVEL_INFO, "ZIG: unable to load file '%s'", filename.c_str());
return false;
}
return ZbLoad_inner(filename.c_str(), fp);
} else {
AddLog(LOG_LEVEL_ERROR, "ZIG: filesystem not enabled");
}
@ -447,6 +452,7 @@ void ZbLoadDump(void) {
// Auto-load all files ending with '.zb'
void ZbAutoload(void) {
ZbAutoLoadFromFlash();
#ifdef USE_UFILESYS
if (ffsp) {
File dir = ffsp->open("/", "r");

View File

@ -0,0 +1,53 @@
/*
xdrv_23_zigbee_7_8_default_plugin.ino - default plugin stored in Flash
Copyright (C) 2021 Theo Arends and Stephan Hadinger
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef USE_ZIGBEE
/********************************************************************
** Default plugin
**
** Below is a the template loaded at boot
** We simulate a read-only file from the filesystem
********************************************************************/
const char Z_DEF_PLUGIN[] PROGMEM =
"#Z2Tv1" "\n"
// bug in IKEA remotes battery, need to double the value
":TRADFRI*," "\n"
":SYMFONISK*," "\n"
"0001/0021=0001/0021,mul:2" "\n" // BatteryPercentage
// "Power" for lumi Door/Window is converted to "Contact"
":lumi.sensor_magnet*," "\n"
"0006/0000=0500/FFF2" "\n" // 0xFFF0 + ZA_Contact
;
/********************************************************************
** Load from flash
********************************************************************/
void ZbAutoLoadFromFlash(void) {
FlashFileImplPtr fp = FlashFileImplPtr(new FlashFileImpl(Z_DEF_PLUGIN));
File f = File(fp);
if (ZbLoad_inner(PSTR("<internal_plugin>"), f)) {
AddLog(LOG_LEVEL_INFO, "ZIG: ZbLoad '%s' loaded successfully", PSTR("<internal_plugin>"));
}
}
#endif // USE_ZIGBEE