mirror of
https://github.com/arendst/Tasmota.git
synced 2025-07-24 03:06:33 +00:00
Merge remote-tracking branch 'upstream/development' into development
* upstream/development: (35 commits) some fixes fix image weblink fix compiler error with use_graph Add support for another variant of the 6-digit TM1637 display Add commands ``DisplayType`` and ``DisplayInvert`` Update xdrv_05_irremote.ino Update xdrv_05_irremote_full.ino Update xdrv_05_irremote_full.ino Update xdrv_05_irremote.ino Update xdrv_20_hue.ino Berry fix rules Add frequency to CSE7761 driver Minor fixes Delete .history/tasmota directory Delete xdrv_20_hue_20210321092519.ino only perform interlock delay once No Discovery Remove text "Module" from GUI main page Refactor DisplayDimmer Use Berry as default for Core2 and Odroid-go ...
This commit is contained in:
commit
3cf5609ad9
@ -18,9 +18,9 @@
|
||||
| USE_WEBSEND_RESPONSE | - | - | - | - | - | - | - |
|
||||
| USE_EMULATION_HUE | - | x | x | - | x | - | - |
|
||||
| USE_EMULATION_WEMO | - | x | x | - | x | - | - |
|
||||
| USE_DISCOVERY | - | - | x | x | - | - | x |
|
||||
| USE_DISCOVERY | - | - | - | - | - | - | - |
|
||||
| WEBSERVER_ADVERTISE | - | - | x | x | - | - | x |
|
||||
| MQTT_HOST_DISCOVERY | - | - | x | x | - | - | x |
|
||||
| MQTT_HOST_DISCOVERY | - | - | - | - | - | - | - |
|
||||
| USE_TIMERS | - | x | x | x | x | x | x |
|
||||
| USE_TIMERS_WEB | - | x | x | x | x | x | x |
|
||||
| USE_SUNRISE | - | x | x | x | x | x | x |
|
||||
|
@ -6,6 +6,7 @@ All notable changes to this project will be documented in this file.
|
||||
## [9.3.1.2]
|
||||
### Added
|
||||
- Commands ``MqttKeepAlive 1..100`` to set Mqtt Keep Alive timer (default 30) and ``MqttTimeout 1..100`` to set Mqtt Socket Timeout (default 4) (#5341)
|
||||
- Commands ``DisplayType`` to select sub-modules where implemented and ``DisplayInvert`` to select inverted display where implemented
|
||||
- Support for TM1638 seven segment display by Ajith Vasudevan (#11031)
|
||||
|
||||
### Changed
|
||||
|
@ -82,16 +82,20 @@ The attached binaries can also be downloaded from http://ota.tasmota.com/tasmota
|
||||
### Added
|
||||
- Commands ``MqttKeepAlive 1..100`` to set Mqtt Keep Alive timer (default 30) and ``MqttTimeout 1..100`` to set Mqtt Socket Timeout (default 4) [#5341](https://github.com/arendst/Tasmota/issues/5341)
|
||||
- Command ``Sensor80 1 <0..7>`` to control MFRC522 RFID antenna gain from 18dB (0) to 48dB (7) [#11073](https://github.com/arendst/Tasmota/issues/11073)
|
||||
- Commands ``DisplayType`` to select sub-modules where implemented and ``DisplayInvert`` to select inverted display where implemented
|
||||
- Support for SML VBUS [#11125](https://github.com/arendst/Tasmota/issues/11125)
|
||||
- Support for NEC and OPTOMA LCD/DLP Projector serial power control by Jan Bubík [#11145](https://github.com/arendst/Tasmota/issues/11145)
|
||||
- Support for XPT2046 touch screen digitizer on ILI9341 display by nonix [#11159](https://github.com/arendst/Tasmota/issues/11159)
|
||||
- Support for zigbee lumi.sensor_wleak [#11200](https://github.com/arendst/Tasmota/issues/11200)
|
||||
- Support for CSE7761 energy monitor as used in ESP32 based Sonoff Dual R3 Pow [#10793](https://github.com/arendst/Tasmota/issues/10793)
|
||||
- Support for TM1638 seven segment display by Ajith Vasudevan [#11031](https://github.com/arendst/Tasmota/issues/11031)
|
||||
- Support for MPU6886 on primary or secondary I2C bus
|
||||
- Allow MCP230xx pinmode from output to input [#11104](https://github.com/arendst/Tasmota/issues/11104)
|
||||
- Berry improvements [#11163](https://github.com/arendst/Tasmota/issues/11163)
|
||||
- Extent compile time SetOptions support [#11204](https://github.com/arendst/Tasmota/issues/11204)
|
||||
- ESP32 Extent BLE [#11212](https://github.com/arendst/Tasmota/issues/11212)
|
||||
- ESP32 support for WS2812 hardware driver via RMT or I2S
|
||||
- ESP32 support for secondary I2C controller
|
||||
|
||||
### Changed
|
||||
- TasmotaSerial library from v3.2.0 to v3.3.0
|
||||
|
23
lib/lib_display/LedControl/LICENSE
Normal file
23
lib/lib_display/LedControl/LICENSE
Normal file
@ -0,0 +1,23 @@
|
||||
LedControl.h - A library for controling Leds with a MAX7219/MAX7221
|
||||
Copyright (c) 2007-2015 Eberhard Fahle
|
||||
|
||||
Permission is hereby granted, free of charge, to any person
|
||||
obtaining a copy of this software and associated documentation
|
||||
files (the "Software"), to deal in the Software without
|
||||
restriction, including without limitation the rights to use,
|
||||
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following
|
||||
conditions:
|
||||
|
||||
This permission notice shall be included in all copies or
|
||||
substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
OTHER DEALINGS IN THE SOFTWARE.
|
25
lib/lib_display/LedControl/README.md
Normal file
25
lib/lib_display/LedControl/README.md
Normal file
@ -0,0 +1,25 @@
|
||||
LedControl
|
||||
==========
|
||||
LedControl is an [Arduino](http://arduino.cc) library for MAX7219 and MAX7221 Led display drivers.
|
||||
The code also works with the [Teensy (3.1)](https://www.pjrc.com/teensy/)
|
||||
|
||||
Documentation
|
||||
-------------
|
||||
Documentation for the library is on the [Github Project Pages](http://wayoda.github.io/LedControl/)
|
||||
|
||||
Download
|
||||
--------
|
||||
The lastest binary version of the Library is always available from the
|
||||
[LedControl Release Page](https://github.com/wayoda/LedControl/releases)
|
||||
|
||||
|
||||
Install
|
||||
-------
|
||||
The library can be installed using the [standard Arduino library install procedure](http://arduino.cc/en/Guide/Libraries#.UwxndHX5PtY)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
28
lib/lib_display/LedControl/keywords.txt
Normal file
28
lib/lib_display/LedControl/keywords.txt
Normal file
@ -0,0 +1,28 @@
|
||||
#######################################
|
||||
# Syntax Coloring Map For LedControl
|
||||
#######################################
|
||||
|
||||
#######################################
|
||||
# Datatypes (KEYWORD1)
|
||||
#######################################
|
||||
|
||||
LedControl KEYWORD1
|
||||
|
||||
#######################################
|
||||
# Methods and Functions (KEYWORD2)
|
||||
#######################################
|
||||
|
||||
shutdown KEYWORD2
|
||||
setScanLimit KEYWORD2
|
||||
setIntensity KEYWORD2
|
||||
clearDisplay KEYWORD2
|
||||
setLed KEYWORD2
|
||||
setRow KEYWORD2
|
||||
setColumn KEYWORD2
|
||||
setDigit KEYWORD2
|
||||
setChar KEYWORD2
|
||||
|
||||
#######################################
|
||||
# Constants (LITERAL1)
|
||||
#######################################
|
||||
|
10
lib/lib_display/LedControl/library.properties
Normal file
10
lib/lib_display/LedControl/library.properties
Normal file
@ -0,0 +1,10 @@
|
||||
name=LedControl
|
||||
version=1.0.6
|
||||
author=Eberhard Fahle <e.fahle@wayoda.org>
|
||||
maintainer=Eberhard Fahle <e.fahle@wayoda.org>
|
||||
sentence=A library for the MAX7219 and the MAX7221 Led display drivers.
|
||||
paragraph=The library supports multiple daisychained drivers and supports Led-Matrix displays as well as 7-Segment displays.
|
||||
category=Display
|
||||
url=http://wayoda.github.io/LedControl/
|
||||
architectures=*
|
||||
|
211
lib/lib_display/LedControl/src/LedControl.cpp
Normal file
211
lib/lib_display/LedControl/src/LedControl.cpp
Normal file
@ -0,0 +1,211 @@
|
||||
/*
|
||||
* LedControl.cpp - A library for controling Leds with a MAX7219/MAX7221
|
||||
* Copyright (c) 2007 Eberhard Fahle
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* This permission notice shall be included in all copies or
|
||||
* substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
#include "LedControl.h"
|
||||
|
||||
//the opcodes for the MAX7221 and MAX7219
|
||||
#define OP_NOOP 0
|
||||
#define OP_DIGIT0 1
|
||||
#define OP_DIGIT1 2
|
||||
#define OP_DIGIT2 3
|
||||
#define OP_DIGIT3 4
|
||||
#define OP_DIGIT4 5
|
||||
#define OP_DIGIT5 6
|
||||
#define OP_DIGIT6 7
|
||||
#define OP_DIGIT7 8
|
||||
#define OP_DECODEMODE 9
|
||||
#define OP_INTENSITY 10
|
||||
#define OP_SCANLIMIT 11
|
||||
#define OP_SHUTDOWN 12
|
||||
#define OP_DISPLAYTEST 15
|
||||
|
||||
LedControl::LedControl(int dataPin, int clkPin, int csPin, int numDevices) {
|
||||
SPI_MOSI=dataPin;
|
||||
SPI_CLK=clkPin;
|
||||
SPI_CS=csPin;
|
||||
if(numDevices<=0 || numDevices>8 )
|
||||
numDevices=8;
|
||||
maxDevices=numDevices;
|
||||
pinMode(SPI_MOSI,OUTPUT);
|
||||
pinMode(SPI_CLK,OUTPUT);
|
||||
pinMode(SPI_CS,OUTPUT);
|
||||
digitalWrite(SPI_CS,HIGH);
|
||||
SPI_MOSI=dataPin;
|
||||
for(int i=0;i<64;i++)
|
||||
status[i]=0x00;
|
||||
for(int i=0;i<maxDevices;i++) {
|
||||
spiTransfer(i,OP_DISPLAYTEST,0);
|
||||
//scanlimit is set to max on startup
|
||||
setScanLimit(i,7);
|
||||
//decode is done in source
|
||||
spiTransfer(i,OP_DECODEMODE,0);
|
||||
clearDisplay(i);
|
||||
//we go into shutdown-mode on startup
|
||||
shutdown(i,true);
|
||||
}
|
||||
}
|
||||
|
||||
int LedControl::getDeviceCount() {
|
||||
return maxDevices;
|
||||
}
|
||||
|
||||
void LedControl::shutdown(int addr, bool b) {
|
||||
if(addr<0 || addr>=maxDevices)
|
||||
return;
|
||||
if(b)
|
||||
spiTransfer(addr, OP_SHUTDOWN,0);
|
||||
else
|
||||
spiTransfer(addr, OP_SHUTDOWN,1);
|
||||
}
|
||||
|
||||
void LedControl::setScanLimit(int addr, int limit) {
|
||||
if(addr<0 || addr>=maxDevices)
|
||||
return;
|
||||
if(limit>=0 && limit<8)
|
||||
spiTransfer(addr, OP_SCANLIMIT,limit);
|
||||
}
|
||||
|
||||
void LedControl::setIntensity(int addr, int intensity) {
|
||||
if(addr<0 || addr>=maxDevices)
|
||||
return;
|
||||
if(intensity>=0 && intensity<16)
|
||||
spiTransfer(addr, OP_INTENSITY,intensity);
|
||||
}
|
||||
|
||||
void LedControl::clearDisplay(int addr) {
|
||||
int offset;
|
||||
|
||||
if(addr<0 || addr>=maxDevices)
|
||||
return;
|
||||
offset=addr*8;
|
||||
for(int i=0;i<8;i++) {
|
||||
status[offset+i]=0;
|
||||
spiTransfer(addr, i+1,status[offset+i]);
|
||||
}
|
||||
}
|
||||
|
||||
void LedControl::setLed(int addr, int row, int column, boolean state) {
|
||||
int offset;
|
||||
byte val=0x00;
|
||||
|
||||
if(addr<0 || addr>=maxDevices)
|
||||
return;
|
||||
if(row<0 || row>7 || column<0 || column>7)
|
||||
return;
|
||||
offset=addr*8;
|
||||
val=B10000000 >> column;
|
||||
if(state)
|
||||
status[offset+row]=status[offset+row]|val;
|
||||
else {
|
||||
val=~val;
|
||||
status[offset+row]=status[offset+row]&val;
|
||||
}
|
||||
spiTransfer(addr, row+1,status[offset+row]);
|
||||
}
|
||||
|
||||
void LedControl::setRow(int addr, int row, byte value) {
|
||||
int offset;
|
||||
if(addr<0 || addr>=maxDevices)
|
||||
return;
|
||||
if(row<0 || row>7)
|
||||
return;
|
||||
offset=addr*8;
|
||||
status[offset+row]=value;
|
||||
spiTransfer(addr, row+1,status[offset+row]);
|
||||
}
|
||||
|
||||
void LedControl::setColumn(int addr, int col, byte value) {
|
||||
byte val;
|
||||
|
||||
if(addr<0 || addr>=maxDevices)
|
||||
return;
|
||||
if(col<0 || col>7)
|
||||
return;
|
||||
for(int row=0;row<8;row++) {
|
||||
val=value >> (7-row);
|
||||
val=val & 0x01;
|
||||
setLed(addr,row,col,val);
|
||||
}
|
||||
}
|
||||
|
||||
void LedControl::setDigit(int addr, int digit, byte value, boolean dp) {
|
||||
int offset;
|
||||
byte v;
|
||||
|
||||
if(addr<0 || addr>=maxDevices)
|
||||
return;
|
||||
if(digit<0 || digit>7 || value>15)
|
||||
return;
|
||||
offset=addr*8;
|
||||
v=pgm_read_byte_near(charTable + value);
|
||||
if(dp)
|
||||
v|=B10000000;
|
||||
status[offset+digit]=v;
|
||||
spiTransfer(addr, digit+1,v);
|
||||
}
|
||||
|
||||
void LedControl::setChar(int addr, int digit, char value, boolean dp) {
|
||||
int offset;
|
||||
byte index,v;
|
||||
|
||||
if(addr<0 || addr>=maxDevices)
|
||||
return;
|
||||
if(digit<0 || digit>7)
|
||||
return;
|
||||
offset=addr*8;
|
||||
index=(byte)value;
|
||||
if(index >127) {
|
||||
//no defined beyond index 127, so we use the space char
|
||||
index=32;
|
||||
}
|
||||
v=pgm_read_byte_near(charTable + index);
|
||||
if(dp)
|
||||
v|=B10000000;
|
||||
status[offset+digit]=v;
|
||||
spiTransfer(addr, digit+1,v);
|
||||
}
|
||||
|
||||
void LedControl::spiTransfer(int addr, volatile byte opcode, volatile byte data) {
|
||||
//Create an array with the data to shift out
|
||||
int offset=addr*2;
|
||||
int maxbytes=maxDevices*2;
|
||||
|
||||
for(int i=0;i<maxbytes;i++)
|
||||
spidata[i]=(byte)0;
|
||||
//put our device data into the array
|
||||
spidata[offset+1]=opcode;
|
||||
spidata[offset]=data;
|
||||
//enable the line
|
||||
digitalWrite(SPI_CS,LOW);
|
||||
//Now shift out the data
|
||||
for(int i=maxbytes;i>0;i--)
|
||||
shiftOut(SPI_MOSI,SPI_CLK,MSBFIRST,spidata[i-1]);
|
||||
//latch the data onto the display
|
||||
digitalWrite(SPI_CS,HIGH);
|
||||
}
|
||||
|
||||
|
190
lib/lib_display/LedControl/src/LedControl.h
Normal file
190
lib/lib_display/LedControl/src/LedControl.h
Normal file
@ -0,0 +1,190 @@
|
||||
/*
|
||||
* LedControl.h - A library for controling Leds with a MAX7219/MAX7221
|
||||
* Copyright (c) 2007 Eberhard Fahle
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* This permission notice shall be included in all copies or
|
||||
* substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef LedControl_h
|
||||
#define LedControl_h
|
||||
|
||||
#include <pgmspace.h>
|
||||
|
||||
#if (ARDUINO >= 100)
|
||||
#include <Arduino.h>
|
||||
#else
|
||||
#include <WProgram.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Segments to be switched on for characters and digits on
|
||||
* 7-Segment Displays
|
||||
*/
|
||||
const static byte charTable [] PROGMEM = {
|
||||
B01111110,B00110000,B01101101,B01111001,B00110011,B01011011,B01011111,B01110000,
|
||||
B01111111,B01111011,B01110111,B00011111,B00001101,B00111101,B01001111,B01000111,
|
||||
B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,
|
||||
B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,
|
||||
B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,
|
||||
B00000000,B00000000,B00000000,B00000000,B10000000,B00000001,B10000000,B00000000,
|
||||
B01111110,B00110000,B01101101,B01111001,B00110011,B01011011,B01011111,B01110000,
|
||||
B01111111,B01111011,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,
|
||||
B00000000,B01110111,B00011111,B00001101,B00111101,B01001111,B01000111,B00000000,
|
||||
B00110111,B00000000,B00000000,B00000000,B00001110,B00000000,B00000000,B00000000,
|
||||
B01100111,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,
|
||||
B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00001000,
|
||||
B00000000,B01110111,B00011111,B00001101,B00111101,B01001111,B01000111,B00000000,
|
||||
B00110111,B00000000,B00000000,B00000000,B00001110,B00000000,B00010101,B00011101,
|
||||
B01100111,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,
|
||||
B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000
|
||||
};
|
||||
|
||||
class LedControl {
|
||||
private :
|
||||
/* The array for shifting the data to the devices */
|
||||
byte spidata[16];
|
||||
/* Send out a single command to the device */
|
||||
void spiTransfer(int addr, byte opcode, byte data);
|
||||
|
||||
/* We keep track of the led-status for all 8 devices in this array */
|
||||
byte status[64];
|
||||
/* Data is shifted out of this pin*/
|
||||
int SPI_MOSI;
|
||||
/* The clock is signaled on this pin */
|
||||
int SPI_CLK;
|
||||
/* This one is driven LOW for chip selectzion */
|
||||
int SPI_CS;
|
||||
/* The maximum number of devices we use */
|
||||
int maxDevices;
|
||||
|
||||
public:
|
||||
/*
|
||||
* Create a new controler
|
||||
* Params :
|
||||
* dataPin pin on the Arduino where data gets shifted out
|
||||
* clockPin pin for the clock
|
||||
* csPin pin for selecting the device
|
||||
* numDevices maximum number of devices that can be controled
|
||||
*/
|
||||
LedControl(int dataPin, int clkPin, int csPin, int numDevices=1);
|
||||
|
||||
/*
|
||||
* Gets the number of devices attached to this LedControl.
|
||||
* Returns :
|
||||
* int the number of devices on this LedControl
|
||||
*/
|
||||
int getDeviceCount();
|
||||
|
||||
/*
|
||||
* Set the shutdown (power saving) mode for the device
|
||||
* Params :
|
||||
* addr The address of the display to control
|
||||
* status If true the device goes into power-down mode. Set to false
|
||||
* for normal operation.
|
||||
*/
|
||||
void shutdown(int addr, bool status);
|
||||
|
||||
/*
|
||||
* Set the number of digits (or rows) to be displayed.
|
||||
* See datasheet for sideeffects of the scanlimit on the brightness
|
||||
* of the display.
|
||||
* Params :
|
||||
* addr address of the display to control
|
||||
* limit number of digits to be displayed (1..8)
|
||||
*/
|
||||
void setScanLimit(int addr, int limit);
|
||||
|
||||
/*
|
||||
* Set the brightness of the display.
|
||||
* Params:
|
||||
* addr the address of the display to control
|
||||
* intensity the brightness of the display. (0..15)
|
||||
*/
|
||||
void setIntensity(int addr, int intensity);
|
||||
|
||||
/*
|
||||
* Switch all Leds on the display off.
|
||||
* Params:
|
||||
* addr address of the display to control
|
||||
*/
|
||||
void clearDisplay(int addr);
|
||||
|
||||
/*
|
||||
* Set the status of a single Led.
|
||||
* Params :
|
||||
* addr address of the display
|
||||
* row the row of the Led (0..7)
|
||||
* col the column of the Led (0..7)
|
||||
* state If true the led is switched on,
|
||||
* if false it is switched off
|
||||
*/
|
||||
void setLed(int addr, int row, int col, boolean state);
|
||||
|
||||
/*
|
||||
* Set all 8 Led's in a row to a new state
|
||||
* Params:
|
||||
* addr address of the display
|
||||
* row row which is to be set (0..7)
|
||||
* value each bit set to 1 will light up the
|
||||
* corresponding Led.
|
||||
*/
|
||||
void setRow(int addr, int row, byte value);
|
||||
|
||||
/*
|
||||
* Set all 8 Led's in a column to a new state
|
||||
* Params:
|
||||
* addr address of the display
|
||||
* col column which is to be set (0..7)
|
||||
* value each bit set to 1 will light up the
|
||||
* corresponding Led.
|
||||
*/
|
||||
void setColumn(int addr, int col, byte value);
|
||||
|
||||
/*
|
||||
* Display a hexadecimal digit on a 7-Segment Display
|
||||
* Params:
|
||||
* addr address of the display
|
||||
* digit the position of the digit on the display (0..7)
|
||||
* value the value to be displayed. (0x00..0x0F)
|
||||
* dp sets the decimal point.
|
||||
*/
|
||||
void setDigit(int addr, int digit, byte value, boolean dp);
|
||||
|
||||
/*
|
||||
* Display a character on a 7-Segment display.
|
||||
* There are only a few characters that make sense here :
|
||||
* '0','1','2','3','4','5','6','7','8','9','0',
|
||||
* 'A','b','c','d','E','F','H','L','P',
|
||||
* '.','-','_',' '
|
||||
* Params:
|
||||
* addr address of the display
|
||||
* digit the position of the character on the display (0..7)
|
||||
* value the character to be displayed.
|
||||
* dp sets the decimal point.
|
||||
*/
|
||||
void setChar(int addr, int digit, char value, boolean dp);
|
||||
};
|
||||
|
||||
#endif //LedControl.h
|
||||
|
||||
|
||||
|
@ -4,24 +4,24 @@
|
||||
|
||||
void MPU6886::I2C_Read_NBytes(uint8_t driver_Addr, uint8_t start_Addr, uint8_t number_Bytes, uint8_t *read_Buffer){
|
||||
|
||||
myWire.beginTransmission(driver_Addr);
|
||||
myWire.write(start_Addr);
|
||||
myWire.endTransmission(false);
|
||||
myWire->beginTransmission(driver_Addr);
|
||||
myWire->write(start_Addr);
|
||||
myWire->endTransmission(false);
|
||||
uint8_t i = 0;
|
||||
myWire.requestFrom(driver_Addr,number_Bytes);
|
||||
myWire->requestFrom(driver_Addr,number_Bytes);
|
||||
|
||||
//! Put read results in the Rx buffer
|
||||
while (myWire.available()) {
|
||||
read_Buffer[i++] = myWire.read();
|
||||
while (myWire->available()) {
|
||||
read_Buffer[i++] = myWire->read();
|
||||
}
|
||||
}
|
||||
|
||||
void MPU6886::I2C_Write_NBytes(uint8_t driver_Addr, uint8_t start_Addr, uint8_t number_Bytes, uint8_t *write_Buffer){
|
||||
|
||||
myWire.beginTransmission(driver_Addr);
|
||||
myWire.write(start_Addr);
|
||||
myWire.write(*write_Buffer);
|
||||
myWire.endTransmission();
|
||||
myWire->beginTransmission(driver_Addr);
|
||||
myWire->write(start_Addr);
|
||||
myWire->write(*write_Buffer);
|
||||
myWire->endTransmission();
|
||||
|
||||
}
|
||||
|
||||
|
@ -71,9 +71,9 @@ class MPU6886 {
|
||||
public:
|
||||
MPU6886(void) {};
|
||||
#ifdef ESP32
|
||||
void setBus(uint32_t _bus) { myWire = _bus ? Wire1 : Wire; };
|
||||
void setBus(uint32_t _bus) { myWire = _bus ? &Wire1 : &Wire; };
|
||||
#else
|
||||
void setBus(uint32_t _bus) { myWire = Wire; };
|
||||
void setBus(uint32_t _bus) { myWire = &Wire; };
|
||||
#endif
|
||||
int Init(void);
|
||||
void getAccelAdc(int16_t* ax, int16_t* ay, int16_t* az);
|
||||
@ -93,7 +93,7 @@ class MPU6886 {
|
||||
// void getAhrsData(float *pitch,float *roll,float *yaw);
|
||||
|
||||
public:
|
||||
TwoWire & myWire = Wire; // default to Wire (bus 0)
|
||||
TwoWire * myWire = &Wire; // default to Wire (bus 0)
|
||||
float aRes, gRes;
|
||||
|
||||
private:
|
||||
|
@ -19,7 +19,7 @@ be_define_native_module(energy, NULL);
|
||||
#else
|
||||
/* @const_object_info_begin
|
||||
module tasmota (scope: global, depend: 1) {
|
||||
getfreeheap, func(l_getFreeHeap)
|
||||
get_free_heap, func(l_getFreeHeap)
|
||||
}
|
||||
@const_object_info_end */
|
||||
#include "../generate/be_fixed_tasmota.h"
|
||||
|
@ -27,6 +27,8 @@ extern int l_getpower(bvm *vm);
|
||||
extern int l_setlight(bvm *vm);
|
||||
extern int l_setpower(bvm *vm);
|
||||
|
||||
extern int l_i2cenabled(bvm *vm);
|
||||
|
||||
// #if !BE_USE_PRECOMPILED_OBJECT
|
||||
#if 1 // TODO we will do pre-compiled later
|
||||
// Class definition
|
||||
@ -39,27 +41,30 @@ void be_load_tasmota_ntvlib(bvm *vm)
|
||||
{ "_rules", NULL },
|
||||
{ "_timers", NULL },
|
||||
{ "_cmd", NULL },
|
||||
{ "getfreeheap", l_getFreeHeap },
|
||||
{ "_drivers", NULL },
|
||||
{ "get_free_heap", l_getFreeHeap },
|
||||
{ "publish", l_publish },
|
||||
{ "cmd", l_cmd },
|
||||
{ "getoption", l_getoption },
|
||||
{ "get_option", l_getoption },
|
||||
{ "millis", l_millis },
|
||||
{ "timereached", l_timereached },
|
||||
{ "time_reached", l_timereached },
|
||||
{ "yield", l_yield },
|
||||
{ "delay", l_delay },
|
||||
{ "scaleuint", l_scaleuint },
|
||||
{ "scale_uint", l_scaleuint },
|
||||
|
||||
{ "respcmnd", l_respCmnd },
|
||||
{ "respcmndstr", l_respCmndStr },
|
||||
{ "respcmnd_done", l_respCmndDone },
|
||||
{ "respcmnd_error", l_respCmndError },
|
||||
{ "respcmnd_failed", l_respCmndFailed },
|
||||
{ "resp_cmnd", l_respCmnd },
|
||||
{ "resp_cmnd_str", l_respCmndStr },
|
||||
{ "resp_cmnd_done", l_respCmndDone },
|
||||
{ "resp_cmnd_error", l_respCmndError },
|
||||
{ "resp_cmnd_failed", l_respCmndFailed },
|
||||
{ "resolvecmnd", l_resolveCmnd },
|
||||
|
||||
{ "getlight", l_getlight },
|
||||
{ "getpower", l_getpower },
|
||||
{ "setlight", l_setlight },
|
||||
{ "setpower", l_setpower },
|
||||
{ "get_light", l_getlight },
|
||||
{ "get_power", l_getpower },
|
||||
{ "set_light", l_setlight },
|
||||
{ "set_power", l_setpower },
|
||||
|
||||
{ "i2c_enabled", l_i2cenabled },
|
||||
|
||||
{ NULL, NULL }
|
||||
};
|
||||
@ -69,7 +74,7 @@ void be_load_tasmota_ntvlib(bvm *vm)
|
||||
#else
|
||||
/* @const_object_info_begin
|
||||
module tasmota (scope: global, depend: 1) {
|
||||
getfreeheap, func(l_getFreeHeap)
|
||||
get_free_heap, func(l_getFreeHeap)
|
||||
}
|
||||
@const_object_info_end */
|
||||
#include "../generate/be_fixed_tasmota.h"
|
||||
|
@ -20,6 +20,7 @@ extern int b_wire_scan(bvm *vm);
|
||||
|
||||
extern int b_wire_validwrite(bvm *vm);
|
||||
extern int b_wire_validread(bvm *vm);
|
||||
extern int b_wire_detect(bvm *vm);
|
||||
|
||||
// #if !BE_USE_PRECOMPILED_OBJECT
|
||||
#if 1 // TODO we will do pre-compiled later
|
||||
@ -28,24 +29,25 @@ void be_load_wirelib(bvm *vm)
|
||||
static const bnfuncinfo members[] = {
|
||||
{ "_bus", NULL }, // bus number
|
||||
{ "init", b_wire_init },
|
||||
{ "_begintransmission", b_wire_begintransmission },
|
||||
{ "_endtransmission", b_wire_endtransmission },
|
||||
{ "_requestfrom", b_wire_requestfrom },
|
||||
{ "_begin_transmission", b_wire_begintransmission },
|
||||
{ "_end_transmission", b_wire_endtransmission },
|
||||
{ "_request_from", b_wire_requestfrom },
|
||||
{ "_available", b_wire_available },
|
||||
{ "_write", b_wire_write },
|
||||
{ "_read", b_wire_read },
|
||||
{ "scan", b_wire_scan },
|
||||
{ "write", b_wire_validwrite },
|
||||
{ "read", b_wire_validread },
|
||||
{ "detect", b_wire_detect },
|
||||
|
||||
{ NULL, NULL }
|
||||
};
|
||||
be_regclass(vm, "Wire", members);
|
||||
be_regclass(vm, "Wire_ntv", members);
|
||||
}
|
||||
#else
|
||||
/* @const_object_info_begin
|
||||
module tasmota (scope: global, depend: 1) {
|
||||
getfreeheap, func(l_getFreeHeap)
|
||||
get_free_heap, func(l_getFreeHeap)
|
||||
}
|
||||
@const_object_info_end */
|
||||
#include "../generate/be_fixed_tasmota.h"
|
||||
|
@ -162,11 +162,27 @@
|
||||
* are not required.
|
||||
* The default is to use the functions in the standard library.
|
||||
**/
|
||||
#ifdef USE_BERRY_PSRAM
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
extern void *berry_malloc(uint32_t size);
|
||||
extern void *berry_realloc(void *ptr, size_t size);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#define BE_EXPLICIT_MALLOC special_malloc
|
||||
#define BE_EXPLICIT_REALLOC special_realloc
|
||||
#else
|
||||
#define BE_EXPLICIT_MALLOC malloc
|
||||
#define BE_EXPLICIT_REALLOC realloc
|
||||
#endif // USE_BERRY_PSRAM
|
||||
|
||||
#define BE_EXPLICIT_ABORT abort
|
||||
#define BE_EXPLICIT_EXIT exit
|
||||
#define BE_EXPLICIT_MALLOC malloc
|
||||
// #define BE_EXPLICIT_MALLOC malloc
|
||||
#define BE_EXPLICIT_FREE free
|
||||
#define BE_EXPLICIT_REALLOC realloc
|
||||
// #define BE_EXPLICIT_REALLOC realloc
|
||||
|
||||
/* Macro: be_assert
|
||||
* Berry debug assertion. Only enabled when BE_DEBUG is active.
|
||||
|
@ -10,11 +10,11 @@ runcolor = nil
|
||||
def runcolor()
|
||||
var pwr = energy.read().find('activepower',0)
|
||||
print(pwr)
|
||||
var red = tasmota.scaleuint(int(pwr), 0, 2500, 0, 255)
|
||||
var red = tasmota.scale_uint(int(pwr), 0, 2500, 0, 255)
|
||||
var green = 255 - red
|
||||
var channels = [red, green, 0]
|
||||
tasmota.setlight({"channels":channels, "bri":64, "power":true})
|
||||
tasmota.settimer(2000, runcolor)
|
||||
tasmota.set_light({"channels":channels, "bri":64, "power":true})
|
||||
tasmota.set_timer(2000, runcolor)
|
||||
end
|
||||
|
||||
#- run animation -#
|
||||
|
@ -1,211 +0,0 @@
|
||||
import json import string
|
||||
tasmota = module("tasmota")
|
||||
def log(m) print(m) end
|
||||
def save() end
|
||||
|
||||
#######
|
||||
import string
|
||||
import json
|
||||
import gc
|
||||
import tasmota
|
||||
#// import alias
|
||||
import tasmota as t
|
||||
|
||||
def charsinstring(s,c)
|
||||
for i:0..size(s)-1
|
||||
for j:0..size(c)-1
|
||||
if s[i] == c[j] return i end
|
||||
end
|
||||
end
|
||||
return -1
|
||||
end
|
||||
|
||||
###
|
||||
class Tasmota
|
||||
var _op, _operators, _rules
|
||||
def init()
|
||||
self._operators = "=<>!|"
|
||||
self._op = [
|
||||
['==', /s1,s2-> str(s1) == str(s2)],
|
||||
['!==',/s1,s2-> str(s1) != str(s2)],
|
||||
['=', /f1,f2-> real(f1) == real(f2)],
|
||||
['!=', /f1,f2-> real(f1) != real(f2)],
|
||||
['>=', /f1,f2-> real(f1) >= real(f2)],
|
||||
['<=', /f1,f2-> real(f1) <= real(f2)],
|
||||
['>', /f1,f2-> real(f1) > real(f2)],
|
||||
['<', /f1,f2-> real(f1) < real(f2)],
|
||||
]
|
||||
self._rules = {}
|
||||
end
|
||||
end
|
||||
###
|
||||
|
||||
tasmota._eqstr=/s1,s2-> str(s1) == str(s2)
|
||||
tasmota._neqstr=/s1,s2-> str(s1) != str(s2)
|
||||
tasmota._eq=/f1,f2-> real(f1) == real(f2)
|
||||
tasmota._neq=/f1,f2-> real(f1) != real(f2)
|
||||
tasmota._gt=/f1,f2-> real(f1) > real(f2)
|
||||
tasmota._lt=/f1,f2-> real(f1) < real(f2)
|
||||
tasmota._ge=/f1,f2-> real(f1) >= real(f2)
|
||||
tasmota._le=/f1,f2-> real(f1) <= real(f2)
|
||||
tasmota._op=[
|
||||
['==',tasmota._eqstr],
|
||||
['!==',tasmota._neqstr],
|
||||
['=',tasmota._eq],
|
||||
['!=',tasmota._neq],
|
||||
['>=',tasmota._ge],
|
||||
['<=',tasmota._le],
|
||||
['>',tasmota._gt],
|
||||
['<',tasmota._lt],
|
||||
]
|
||||
tasmota._operators="=<>!|"
|
||||
|
||||
# split the item when there is an operator, returns a list of (left,op,right)
|
||||
# ex: "Dimmer>50" -> ["Dimmer",tasmota_gt,"50"]
|
||||
tasmota.find_op = def (item)
|
||||
var pos = charsinstring(item, tasmota._operators)
|
||||
if pos>=0
|
||||
var op_split = string.split(item,pos)
|
||||
#print(op_split)
|
||||
var op_left = op_split[0]
|
||||
var op_rest = op_split[1]
|
||||
# iterate through operators
|
||||
for op:tasmota._op
|
||||
if string.find(op_rest,op[0]) == 0
|
||||
var op_func = op[1]
|
||||
var op_right = string.split(op_rest,size(op[0]))[1]
|
||||
return [op_left,op_func,op_right]
|
||||
end
|
||||
end
|
||||
end
|
||||
return [item, nil, nil]
|
||||
end
|
||||
|
||||
|
||||
def findkeyi(m,keyi)
|
||||
var keyu = string.toupper(keyi)
|
||||
if classof(m) == map
|
||||
for k:m.keys()
|
||||
if string.toupper(k)==keyu || keyi=='?'
|
||||
return k
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
tasmota.try_rule = def (ev, rule, f)
|
||||
var rl_list = tasmota.find_op(rule)
|
||||
var e=ev
|
||||
var rl=string.split(rl_list[0],'#')
|
||||
for it:rl
|
||||
found=findkeyi(e,it)
|
||||
if found == nil
|
||||
return false
|
||||
end
|
||||
e=e[found]
|
||||
end
|
||||
# check if condition is true
|
||||
if rl_list[1]
|
||||
# did we find a function
|
||||
if !rl_list[1](e,rl_list[2])
|
||||
# condition is not met
|
||||
return false
|
||||
end
|
||||
end
|
||||
f(e,ev)
|
||||
return true
|
||||
end
|
||||
tasmota_rules={}
|
||||
tasmota.rule = def(pat,f) tasmota_rules[pat] = f end
|
||||
|
||||
tasmota.exec_rules = def (ev_json)
|
||||
var ev = json.load(ev_json)
|
||||
var ret = false
|
||||
if ev == nil
|
||||
log('BRY: ERROR, bad json: '+ev_json, 3)
|
||||
end
|
||||
for r:tasmota_rules.keys()
|
||||
ret = tasmota.try_rule(ev,r,tasmota_rules[r]) || ret
|
||||
end
|
||||
return ret
|
||||
end
|
||||
|
||||
tasmota.delay = def(ms)
|
||||
tend = tasmota.millis(ms)
|
||||
while !tasmota.timereached(tend)
|
||||
tasmota.yield()
|
||||
end
|
||||
end
|
||||
|
||||
def load(f)
|
||||
try
|
||||
if f[0] != '/' f = '/' + f end
|
||||
compile(f,'file')()
|
||||
except .. as e
|
||||
log(string.format("BRY: could not load file '%s' - %s",f,e))
|
||||
end
|
||||
end
|
||||
|
||||
#- Test
|
||||
#################################################################
|
||||
|
||||
def log(m) print(m) end
|
||||
def my_rule(e,ev) log("e1="+str(e)+" e2="+str(ev)) end
|
||||
|
||||
tasmota.rule("ZBRECEIVED#?#LINKQUALITY", my_rule)
|
||||
tasmota.rule("ZBRECEIVED#0x1234", my_rule)
|
||||
|
||||
tasmota.rule("ZBRECEIVED#?#LINKQUALITY<10", my_rule)
|
||||
|
||||
tasmota.rule("Dimmer>50", my_rule)
|
||||
tasmota.rule("Dimmer=01", my_rule)
|
||||
|
||||
|
||||
tasmota.rule("Color==022600", my_rule)
|
||||
|
||||
tasmota.exec_rules('{"Color":"022600"}')
|
||||
|
||||
tasmota.exec_rules('{"ZbReceived":{"0x1234":{"Device":"0x1234","LinkQuality":50}}}')
|
||||
|
||||
tasmota.exec_rules('{"Dimmer":10}')
|
||||
|
||||
|
||||
|
||||
# tasmota.rule("DIMMER", my_rule)
|
||||
# tasmota.rule("DIMMER#DATA#DATA", my_rule)
|
||||
# tasmota.exec_rules('{"Dimmer":{"Data":50}}')
|
||||
|
||||
|
||||
-#
|
||||
|
||||
#-
|
||||
tasmota.find_op("aaa")
|
||||
tasmota.find_op("aaa>50")
|
||||
-#
|
||||
|
||||
#-
|
||||
# Example of backlog equivalent
|
||||
|
||||
def backlog(cmd_list)
|
||||
delay_backlog = tasmota.getoption(34) # in milliseconds
|
||||
delay = 0
|
||||
for cmd:cmd_list
|
||||
tasmota.timer(delay, /-> tasmota.cmd(cmd))
|
||||
delay = delay + delay_backlog
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
br def backlog(cmd_list) delay_backlog = tasmota.getoption(34) delay = 0 for cmd:cmd_list tasmota.timer(delay, /-> tasmota.cmd(cmd)) delay = delay + delay_backlog end end
|
||||
|
||||
br backlog( [ "Power 0", "Status 4", "Power 1" ] )
|
||||
|
||||
-#
|
||||
|
||||
#-
|
||||
|
||||
tasmota.delay = def(ms) tend = tasmota.millis(ms) log(str(tasmota.millis())) while !tasmota.timereached(tend) end log(str(tasmota.millis())) end
|
||||
tasmota.delay = def(ms) a=0 tend = tasmota.millis(ms) log(str(tasmota.millis())) while !tasmota.timereached(tend) a=a+1 end log(str(tasmota.millis())) log(str(a)) end
|
||||
|
||||
-#
|
@ -56,6 +56,7 @@ uint8_t hk_services;
|
||||
|
||||
extern void Ext_Replace_Cmd_Vars(char *srcbuf, uint32_t srcsize, char *dstbuf, uint32_t dstsize);
|
||||
extern uint32_t Ext_UpdVar(char *vname, float *fvar, uint32_t mode);
|
||||
extern void Ext_toLog(char *str);
|
||||
|
||||
#define MAX_HAP_DEFS 16
|
||||
struct HAP_DESC {
|
||||
@ -64,6 +65,7 @@ struct HAP_DESC {
|
||||
char var2_name[12];
|
||||
char var3_name[12];
|
||||
char var4_name[12];
|
||||
char var5_name[12];
|
||||
uint8_t hap_cid;
|
||||
uint8_t type;
|
||||
hap_acc_t *accessory;
|
||||
@ -157,8 +159,8 @@ const struct HAP_CHAR_TABLE {
|
||||
{HAP_CHAR_UUID_CURRENT_RELATIVE_HUMIDITY,'f',0},
|
||||
{HAP_CHAR_UUID_CURRENT_AMBIENT_LIGHT_LEVEL,'f',0},
|
||||
{HAP_CHAR_UUID_BATTERY_LEVEL,'u',0},
|
||||
{HAP_CHAR_UUID_STATUS_LOW_BATTERY,'b',1},
|
||||
{HAP_CHAR_UUID_CHARGING_STATE,'b',2},
|
||||
{HAP_CHAR_UUID_STATUS_LOW_BATTERY,'u',1},
|
||||
{HAP_CHAR_UUID_CHARGING_STATE,'u',2},
|
||||
{HAP_CHAR_UUID_ON,'b',0},
|
||||
{HAP_CHAR_UUID_HUE,'f',1},
|
||||
{HAP_CHAR_UUID_SATURATION,'f',2},
|
||||
@ -282,7 +284,7 @@ void hap_update_from_vars(void) {
|
||||
new_val.u = fvar;
|
||||
hap_char_update_val(hc, &new_val);
|
||||
}
|
||||
hc = hap_serv_get_char_by_uuid(hap_devs[cnt].service, HAP_CHAR_UUID_STATUS_LOW_BATTERY);
|
||||
hc = hap_serv_get_char_by_uuid(hap_devs[cnt].service, HAP_CHAR_UUID_CHARGING_STATE);
|
||||
if (Ext_UpdVar(hap_devs[cnt].var3_name, &fvar, 0)) {
|
||||
new_val.u = fvar;
|
||||
hap_char_update_val(hc, &new_val);
|
||||
@ -332,6 +334,13 @@ void hap_update_from_vars(void) {
|
||||
new_val.u = fvar;
|
||||
hap_char_update_val(hc, &new_val);
|
||||
}
|
||||
if (hap_devs[cnt].var5_name[0]) {
|
||||
hc = hap_serv_get_char_by_uuid(hap_devs[cnt].service, HAP_CHAR_UUID_COLOR_TEMPERATURE);
|
||||
if (Ext_UpdVar(hap_devs[cnt].var5_name, &fvar, 0)) {
|
||||
new_val.u = fvar;
|
||||
hap_char_update_val(hc, &new_val);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -454,6 +463,7 @@ uint32_t str2c(char **sp, char *vp, uint32_t len) {
|
||||
} else {
|
||||
if (strlen(*sp)) {
|
||||
strlcpy(vp, *sp, len);
|
||||
*sp = lp + strlen(*sp);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@ -520,19 +530,16 @@ static void smart_outlet_thread_entry(void *p) {
|
||||
if (str2c(&lp1, hap_devs[index].var_name, sizeof(hap_devs[index].var_name))) {
|
||||
goto nextline;
|
||||
}
|
||||
if (hap_devs[index].hap_cid == HAP_CID_LIGHTING) {
|
||||
// get 3 add vars
|
||||
if (str2c(&lp1, hap_devs[index].var2_name, sizeof(hap_devs[index].var2_name))) {
|
||||
goto nextline;
|
||||
}
|
||||
if (str2c(&lp1, hap_devs[index].var3_name, sizeof(hap_devs[index].var3_name))) {
|
||||
goto nextline;
|
||||
}
|
||||
if (str2c(&lp1, hap_devs[index].var4_name, sizeof(hap_devs[index].var4_name))) {
|
||||
goto nextline;
|
||||
}
|
||||
}
|
||||
|
||||
hap_devs[index].var2_name[0] = 0;
|
||||
hap_devs[index].var3_name[0] = 0;
|
||||
hap_devs[index].var4_name[0] = 0;
|
||||
hap_devs[index].var5_name[0] = 0;
|
||||
|
||||
str2c(&lp1, hap_devs[index].var2_name, sizeof(hap_devs[index].var2_name));
|
||||
str2c(&lp1, hap_devs[index].var3_name, sizeof(hap_devs[index].var3_name));
|
||||
str2c(&lp1, hap_devs[index].var4_name, sizeof(hap_devs[index].var4_name));
|
||||
str2c(&lp1, hap_devs[index].var5_name, sizeof(hap_devs[index].var5_name));
|
||||
|
||||
hap_acc_cfg_t hap_cfg;
|
||||
hap_cfg.name = hap_devs[index].hap_name;
|
||||
@ -557,12 +564,20 @@ static void smart_outlet_thread_entry(void *p) {
|
||||
{ float fvar = 0;
|
||||
Ext_UpdVar(hap_devs[index].var_name, &fvar, 0);
|
||||
hap_devs[index].service = hap_serv_lightbulb_create(fvar);
|
||||
Ext_UpdVar(hap_devs[index].var2_name, &fvar, 0);
|
||||
ret |= hap_serv_add_char(hap_devs[index].service, hap_char_hue_create(fvar));
|
||||
Ext_UpdVar(hap_devs[index].var3_name, &fvar, 0);
|
||||
ret |= hap_serv_add_char(hap_devs[index].service, hap_char_saturation_create(fvar));
|
||||
if (hap_devs[index].var2_name[0]) {
|
||||
Ext_UpdVar(hap_devs[index].var2_name, &fvar, 0);
|
||||
ret |= hap_serv_add_char(hap_devs[index].service, hap_char_hue_create(fvar));
|
||||
}
|
||||
if (hap_devs[index].var3_name[0]) {
|
||||
Ext_UpdVar(hap_devs[index].var3_name, &fvar, 0);
|
||||
ret |= hap_serv_add_char(hap_devs[index].service, hap_char_saturation_create(fvar));
|
||||
}
|
||||
Ext_UpdVar(hap_devs[index].var4_name, &fvar, 0);
|
||||
ret |= hap_serv_add_char(hap_devs[index].service, hap_char_brightness_create(fvar));
|
||||
if (hap_devs[index].var5_name[0]) {
|
||||
Ext_UpdVar(hap_devs[index].var5_name, &fvar, 0);
|
||||
ret |= hap_serv_add_char(hap_devs[index].service, hap_char_color_temperature_create(fvar));
|
||||
}
|
||||
}
|
||||
break;
|
||||
case HAP_CID_OUTLET:
|
||||
@ -681,14 +696,14 @@ nextline:
|
||||
// vTaskDelete(NULL);
|
||||
while (1) {
|
||||
delay(500);
|
||||
// hap_update_from_vars();
|
||||
hap_update_from_vars();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define HK_PASSCODE "111-11-111"
|
||||
int hap_loop_stop(void);
|
||||
extern void Ext_toLog(char *str);
|
||||
|
||||
|
||||
void homekit_main(char *desc, uint32_t flag ) {
|
||||
if (desc) {
|
||||
|
@ -647,6 +647,9 @@
|
||||
#define D_SENSOR_TM1638_CLK "TM1638 CLK"
|
||||
#define D_SENSOR_TM1638_DIO "TM1638 DIO"
|
||||
#define D_SENSOR_TM1638_STB "TM1638 STB"
|
||||
#define D_SENSOR_MAX7219_DIN "MAX7219 DIN"
|
||||
#define D_SENSOR_MAX7219_CS "MAX7219 CS"
|
||||
#define D_SENSOR_MAX7219_CLK "MAX7219 CLK"
|
||||
#define D_SENSOR_HX711_SCK "HX711 SCK"
|
||||
#define D_SENSOR_HX711_DAT "HX711 DAT"
|
||||
#define D_SENSOR_FTC532 "FTC532"
|
||||
|
@ -646,6 +646,9 @@
|
||||
#define D_SENSOR_TM1638_CLK "TM1638 CLK"
|
||||
#define D_SENSOR_TM1638_DIO "TM1638 DIO"
|
||||
#define D_SENSOR_TM1638_STB "TM1638 STB"
|
||||
#define D_SENSOR_MAX7219_DIN "MAX7219 DIN"
|
||||
#define D_SENSOR_MAX7219_CS "MAX7219 CS"
|
||||
#define D_SENSOR_MAX7219_CLK "MAX7219 CLK"
|
||||
#define D_SENSOR_HX711_SCK "HX711 SCK"
|
||||
#define D_SENSOR_HX711_DAT "HX711 DAT"
|
||||
#define D_SENSOR_FTC532 "FTC532"
|
||||
|
@ -647,6 +647,9 @@
|
||||
#define D_SENSOR_TM1638_CLK "TM1638 CLK"
|
||||
#define D_SENSOR_TM1638_DIO "TM1638 DIO"
|
||||
#define D_SENSOR_TM1638_STB "TM1638 STB"
|
||||
#define D_SENSOR_MAX7219_DIN "MAX7219 DIN"
|
||||
#define D_SENSOR_MAX7219_CS "MAX7219 CS"
|
||||
#define D_SENSOR_MAX7219_CLK "MAX7219 CLK"
|
||||
#define D_SENSOR_HX711_SCK "HX711 SCK"
|
||||
#define D_SENSOR_HX711_DAT "HX711 DAT"
|
||||
#define D_SENSOR_FTC532 "FTC532"
|
||||
|
@ -647,6 +647,9 @@
|
||||
#define D_SENSOR_TM1638_CLK "TM1638 CLK"
|
||||
#define D_SENSOR_TM1638_DIO "TM1638 DIO"
|
||||
#define D_SENSOR_TM1638_STB "TM1638 STB"
|
||||
#define D_SENSOR_MAX7219_DIN "MAX7219 DIN"
|
||||
#define D_SENSOR_MAX7219_CS "MAX7219 CS"
|
||||
#define D_SENSOR_MAX7219_CLK "MAX7219 CLK"
|
||||
#define D_SENSOR_HX711_SCK "HX711 SCK"
|
||||
#define D_SENSOR_HX711_DAT "HX711 DAT"
|
||||
#define D_SENSOR_FTC532 "FTC532"
|
||||
|
@ -647,6 +647,9 @@
|
||||
#define D_SENSOR_TM1638_CLK "TM1638 CLK"
|
||||
#define D_SENSOR_TM1638_DIO "TM1638 DIO"
|
||||
#define D_SENSOR_TM1638_STB "TM1638 STB"
|
||||
#define D_SENSOR_MAX7219_DIN "MAX7219 DIN"
|
||||
#define D_SENSOR_MAX7219_CS "MAX7219 CS"
|
||||
#define D_SENSOR_MAX7219_CLK "MAX7219 CLK"
|
||||
#define D_SENSOR_HX711_SCK "HX711 SCK"
|
||||
#define D_SENSOR_HX711_DAT "HX711 DAT"
|
||||
#define D_SENSOR_FTC532 "FTC532"
|
||||
|
@ -647,6 +647,9 @@
|
||||
#define D_SENSOR_TM1638_CLK "TM1638 CLK"
|
||||
#define D_SENSOR_TM1638_DIO "TM1638 DIO"
|
||||
#define D_SENSOR_TM1638_STB "TM1638 STB"
|
||||
#define D_SENSOR_MAX7219_DIN "MAX7219 DIN"
|
||||
#define D_SENSOR_MAX7219_CS "MAX7219 CS"
|
||||
#define D_SENSOR_MAX7219_CLK "MAX7219 CLK"
|
||||
#define D_SENSOR_HX711_SCK "HX711 SCK"
|
||||
#define D_SENSOR_HX711_DAT "HX711 DAT"
|
||||
#define D_SENSOR_FTC532 "FTC532"
|
||||
|
@ -647,6 +647,9 @@
|
||||
#define D_SENSOR_TM1638_CLK "TM1638 CLK"
|
||||
#define D_SENSOR_TM1638_DIO "TM1638 DIO"
|
||||
#define D_SENSOR_TM1638_STB "TM1638 STB"
|
||||
#define D_SENSOR_MAX7219_DIN "MAX7219 DIN"
|
||||
#define D_SENSOR_MAX7219_CS "MAX7219 CS"
|
||||
#define D_SENSOR_MAX7219_CLK "MAX7219 CLK"
|
||||
#define D_SENSOR_HX711_SCK "HX711 SCK"
|
||||
#define D_SENSOR_HX711_DAT "HX711 DAT"
|
||||
#define D_SENSOR_FTC532 "FTC532"
|
||||
|
@ -362,7 +362,7 @@
|
||||
#define D_TRANSFER_STARTED "Transfert lancé"
|
||||
#define D_UPLOAD_ERR_1 "Aucun fichier sélectionné"
|
||||
#define D_UPLOAD_ERR_2 "Espace insuffisant"
|
||||
#define D_UPLOAD_ERR_3 "Invalid file signature"
|
||||
#define D_UPLOAD_ERR_3 "Signature de fichier invalide"
|
||||
#define D_UPLOAD_ERR_4 "La taille du programme à flasher est plus grande que la taille réelle de la mémoire flash"
|
||||
#define D_UPLOAD_ERR_5 "Erreur de comparaison du buffer de téléchargement"
|
||||
#define D_UPLOAD_ERR_6 "Téléchargement échoué. Activer WebLog 3"
|
||||
@ -602,7 +602,7 @@
|
||||
#define D_SENSOR_WS2812 "WS2812"
|
||||
#define D_SENSOR_DFR562 "MP3 Player"
|
||||
#define D_SENSOR_IRSEND "IR TX"
|
||||
#define D_SENSOR_SWITCH "Inter." // Suffix "1"
|
||||
#define D_SENSOR_SWITCH "Inter" // Suffix "1"
|
||||
#define D_SENSOR_BUTTON "Bouton" // Suffix "1"
|
||||
#define D_SENSOR_RELAY "Relais" // Suffix "1i"
|
||||
#define D_SENSOR_LED "LED" // Suffix "1i"
|
||||
@ -624,8 +624,8 @@
|
||||
#define D_SENSOR_SPI_MOSI "SPI MOSI"
|
||||
#define D_SENSOR_SPI_CLK "SPI CLK"
|
||||
#define D_SENSOR_BACKLIGHT "RétroÉcl"
|
||||
#define D_SENSOR_PMS5003_TX "PMS5003 Tx"
|
||||
#define D_SENSOR_PMS5003_RX "PMS5003 Rx"
|
||||
#define D_SENSOR_PMS5003_TX "PMS5003 TX"
|
||||
#define D_SENSOR_PMS5003_RX "PMS5003 RX"
|
||||
#define D_SENSOR_SDS0X1_RX "SDS0X1 RX"
|
||||
#define D_SENSOR_SDS0X1_TX "SDS0X1 TX"
|
||||
#define D_SENSOR_HPMA_RX "HPMA RX"
|
||||
@ -634,19 +634,22 @@
|
||||
#define D_SENSOR_SBR_TX "SerBr TX"
|
||||
#define D_SENSOR_SR04_TRIG "SR04 Tri/TX"
|
||||
#define D_SENSOR_SR04_ECHO "SR04 Ech/RX"
|
||||
#define D_SENSOR_SDM72_TX "SDM72 Tx"
|
||||
#define D_SENSOR_SDM72_RX "SDM72 Rx"
|
||||
#define D_SENSOR_SDM72_TX "SDM72 TX"
|
||||
#define D_SENSOR_SDM72_RX "SDM72 RX"
|
||||
#define D_SENSOR_SDM120_TX "SDMx20 TX"
|
||||
#define D_SENSOR_SDM120_RX "SDMx20 RX"
|
||||
#define D_SENSOR_SDM630_TX "SDM630 TX"
|
||||
#define D_SENSOR_SDM630_RX "SDM630 RX"
|
||||
#define D_SENSOR_WE517_TX "WE517 Tx"
|
||||
#define D_SENSOR_WE517_RX "WE517 Rx"
|
||||
#define D_SENSOR_WE517_TX "WE517 TX"
|
||||
#define D_SENSOR_WE517_RX "WE517 RX"
|
||||
#define D_SENSOR_TM1637_CLK "TM1637 CLK"
|
||||
#define D_SENSOR_TM1637_DIO "TM1637 DIO"
|
||||
#define D_SENSOR_TM1638_CLK "TM1638 CLK"
|
||||
#define D_SENSOR_TM1638_DIO "TM1638 DIO"
|
||||
#define D_SENSOR_TM1638_STB "TM1638 STB"
|
||||
#define D_SENSOR_MAX7219_DIN "MAX7219 DIN"
|
||||
#define D_SENSOR_MAX7219_CS "MAX7219 CS"
|
||||
#define D_SENSOR_MAX7219_CLK "MAX7219 CLK"
|
||||
#define D_SENSOR_HX711_SCK "HX711 SCK"
|
||||
#define D_SENSOR_HX711_DAT "HX711 DAT"
|
||||
#define D_SENSOR_FTC532 "FTC532"
|
||||
@ -657,8 +660,8 @@
|
||||
#define D_SENSOR_RFRECV "RF RX"
|
||||
#define D_SENSOR_TUYA_TX "Tuya TX"
|
||||
#define D_SENSOR_TUYA_RX "Tuya RX"
|
||||
#define D_SENSOR_MGC3130_XFER "MGC3130 Xfr"
|
||||
#define D_SENSOR_MGC3130_RESET "MGC3130 Rst"
|
||||
#define D_SENSOR_MGC3130_XFER "MGC3130 XFR"
|
||||
#define D_SENSOR_MGC3130_RESET "MGC3130 RST"
|
||||
#define D_SENSOR_SSPI_MISO "SSPI MISO"
|
||||
#define D_SENSOR_SSPI_MOSI "SSPI MOSI"
|
||||
#define D_SENSOR_SSPI_SCLK "SSPI SCLK"
|
||||
@ -677,9 +680,9 @@
|
||||
#define D_SENSOR_HJL_CF "BL0937 CF"
|
||||
#define D_SENSOR_MCP39F5_TX "MCP39F5 TX"
|
||||
#define D_SENSOR_MCP39F5_RX "MCP39F5 RX"
|
||||
#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst"
|
||||
#define D_SENSOR_CSE7761_TX "CSE7761 Tx"
|
||||
#define D_SENSOR_CSE7761_RX "CSE7761 Rx"
|
||||
#define D_SENSOR_MCP39F5_RST "MCP39F5 RST"
|
||||
#define D_SENSOR_CSE7761_TX "CSE7761 TX"
|
||||
#define D_SENSOR_CSE7761_RX "CSE7761 RX"
|
||||
#define D_SENSOR_CSE7766_TX "CSE7766 TX"
|
||||
#define D_SENSOR_CSE7766_RX "CSE7766 RX"
|
||||
#define D_SENSOR_PN532_TX "PN532 TX"
|
||||
@ -687,8 +690,8 @@
|
||||
#define D_SENSOR_SM16716_CLK "SM16716 CLK"
|
||||
#define D_SENSOR_SM16716_DAT "SM16716 DAT"
|
||||
#define D_SENSOR_SM16716_POWER "SM16716 PWR"
|
||||
#define D_SENSOR_P9813_CLK "P9813 Clk"
|
||||
#define D_SENSOR_P9813_DAT "P9813 Dat"
|
||||
#define D_SENSOR_P9813_CLK "P9813 CLK"
|
||||
#define D_SENSOR_P9813_DAT "P9813 DAT"
|
||||
#define D_SENSOR_MY92X1_DI "MY92x1 DI"
|
||||
#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI"
|
||||
#define D_SENSOR_ARIRFRCV "ALux IrRcv"
|
||||
@ -696,14 +699,14 @@
|
||||
#define D_SENSOR_TXD "Série TX"
|
||||
#define D_SENSOR_RXD "Série RX"
|
||||
#define D_SENSOR_ROTARY "Rotary" // Suffix "1A"
|
||||
#define D_SENSOR_HRE_CLOCK "HRE Clock"
|
||||
#define D_SENSOR_HRE_DATA "HRE Data"
|
||||
#define D_SENSOR_HRE_CLOCK "HRE CLK"
|
||||
#define D_SENSOR_HRE_DATA "HRE DAT"
|
||||
#define D_SENSOR_ADE7953_IRQ "ADE7953 IRQ"
|
||||
#define D_SENSOR_BUZZER "Buzzer"
|
||||
#define D_SENSOR_OLED_RESET "OLED Reset"
|
||||
#define D_SENSOR_OLED_RESET "OLED RST"
|
||||
#define D_SENSOR_ZIGBEE_TXD "ZigBee TX"
|
||||
#define D_SENSOR_ZIGBEE_RXD "ZigBee RX"
|
||||
#define D_SENSOR_ZIGBEE_RST "ZigBee Rst"
|
||||
#define D_SENSOR_ZIGBEE_RST "ZigBee RST"
|
||||
#define D_SENSOR_SOLAXX1_TX "SolaxX1 TX"
|
||||
#define D_SENSOR_SOLAXX1_RX "SolaxX1 RX"
|
||||
#define D_SENSOR_IBEACON_TX "iBeacon TX"
|
||||
@ -714,36 +717,36 @@
|
||||
#define D_SENSOR_A4988_STP "A4988 STP"
|
||||
#define D_SENSOR_A4988_ENA "A4988 ENA"
|
||||
#define D_SENSOR_A4988_MS1 "A4988 MS1"
|
||||
#define D_SENSOR_OUTPUT_HI "Output Hi"
|
||||
#define D_SENSOR_OUTPUT_LO "Output Lo"
|
||||
#define D_SENSOR_AS608_TX "AS608 Tx"
|
||||
#define D_SENSOR_AS608_RX "AS608 Rx"
|
||||
#define D_SENSOR_OUTPUT_HI "Sortie Hi"
|
||||
#define D_SENSOR_OUTPUT_LO "Sortie Lo"
|
||||
#define D_SENSOR_AS608_TX "AS608 TX"
|
||||
#define D_SENSOR_AS608_RX "AS608 RX"
|
||||
#define D_SENSOR_DDS2382_TX "DDS238-2 TX"
|
||||
#define D_SENSOR_DDS2382_RX "DDS238-2 RX"
|
||||
#define D_SENSOR_DDSU666_TX "DDSU666 TX"
|
||||
#define D_SENSOR_DDSU666_RX "DDSU666 RX"
|
||||
#define D_SENSOR_SM2135_CLK "SM2135 Clk"
|
||||
#define D_SENSOR_SM2135_DAT "SM2135 Dat"
|
||||
#define D_SENSOR_SM2135_CLK "SM2135 CLK"
|
||||
#define D_SENSOR_SM2135_DAT "SM2135 DAT"
|
||||
#define D_SENSOR_DEEPSLEEP "Hibernation"
|
||||
#define D_SENSOR_EXS_ENABLE "EXS Enable"
|
||||
#define D_SENSOR_CLIENT_TX "Esclave TX"
|
||||
#define D_SENSOR_CLIENT_RX "Esclave RX"
|
||||
#define D_SENSOR_CLIENT_RESET "Esclave Rst"
|
||||
#define D_SENSOR_CLIENT_RESET "Esclave RST"
|
||||
#define D_SENSOR_GPS_RX "GPS RX"
|
||||
#define D_SENSOR_GPS_TX "GPS TX"
|
||||
#define D_SENSOR_HM10_RX "HM10 RX"
|
||||
#define D_SENSOR_HM10_TX "HM10 TX"
|
||||
#define D_SENSOR_LE01MR_RX "LE-01MR Rx"
|
||||
#define D_SENSOR_LE01MR_TX "LE-01MR Tx"
|
||||
#define D_SENSOR_BL0940_RX "BL0940 Rx"
|
||||
#define D_SENSOR_LE01MR_RX "LE-01MR RX"
|
||||
#define D_SENSOR_LE01MR_TX "LE-01MR TX"
|
||||
#define D_SENSOR_BL0940_RX "BL0940 RX"
|
||||
#define D_SENSOR_CC1101_GDO0 "CC1101 GDO0"
|
||||
#define D_SENSOR_CC1101_GDO2 "CC1101 GDO2"
|
||||
#define D_SENSOR_HRXL_RX "HRXL Rx"
|
||||
#define D_SENSOR_DYP_RX "DYP Rx"
|
||||
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
|
||||
#define D_SENSOR_HRXL_RX "HRXL RX"
|
||||
#define D_SENSOR_DYP_RX "DYP RX"
|
||||
#define D_SENSOR_ELECTRIQ_MOODL "MOODL TX"
|
||||
#define D_SENSOR_AS3935 "AS3935"
|
||||
#define D_SENSOR_WINDMETER_SPEED "Anémomètre"
|
||||
#define D_SENSOR_TELEINFO_RX "TInfo Rx"
|
||||
#define D_SENSOR_TELEINFO_RX "TInfo RX"
|
||||
#define D_SENSOR_TELEINFO_ENABLE "TInfo En"
|
||||
#define D_SENSOR_LMT01_PULSE "LMT01 Impulsion"
|
||||
#define D_SENSOR_ADC_INPUT "ADC Entrée"
|
||||
@ -769,14 +772,14 @@
|
||||
#define D_SENSOR_ETH_PHY_POWER "ETH POWER"
|
||||
#define D_SENSOR_ETH_PHY_MDC "ETH MDC"
|
||||
#define D_SENSOR_ETH_PHY_MDIO "ETH MDIO"
|
||||
#define D_SENSOR_TCP_TXD "TCP Tx"
|
||||
#define D_SENSOR_TCP_RXD "TCP Rx"
|
||||
#define D_SENSOR_TCP_TXD "TCP TX"
|
||||
#define D_SENSOR_TCP_RXD "TCP RX"
|
||||
#define D_SENSOR_IEM3000_TX "iEM3000 TX"
|
||||
#define D_SENSOR_IEM3000_RX "iEM3000 RX"
|
||||
#define D_SENSOR_MIEL_HVAC_TX "MiEl HVAC Tx"
|
||||
#define D_SENSOR_MIEL_HVAC_RX "MiEl HVAC Rx"
|
||||
#define D_SENSOR_PROJECTOR_CTRL_TX "DLP Tx"
|
||||
#define D_SENSOR_PROJECTOR_CTRL_RX "DLP Rx"
|
||||
#define D_SENSOR_MIEL_HVAC_TX "MiEl HVAC TX"
|
||||
#define D_SENSOR_MIEL_HVAC_RX "MiEl HVAC RX"
|
||||
#define D_SENSOR_PROJECTOR_CTRL_TX "DLP TX"
|
||||
#define D_SENSOR_PROJECTOR_CTRL_RX "DLP RX"
|
||||
#define D_SENSOR_SHELLY_DIMMER_BOOT0 "SHD Boot 0"
|
||||
#define D_SENSOR_SHELLY_DIMMER_RST_INV "SHD Reset"
|
||||
#define D_SENSOR_RC522_RST "RC522 Rst"
|
||||
@ -799,8 +802,8 @@
|
||||
#define D_SENSOR_SDCARD_CS "CarteSD CS"
|
||||
#define D_SENSOR_WIEGAND_D0 "Wiegand D0"
|
||||
#define D_SENSOR_WIEGAND_D1 "Wiegand D1"
|
||||
#define D_SENSOR_NEOPOOL_TX "NeoPool Tx"
|
||||
#define D_SENSOR_NEOPOOL_RX "NeoPool Rx"
|
||||
#define D_SENSOR_NEOPOOL_TX "NeoPool TX"
|
||||
#define D_SENSOR_NEOPOOL_RX "NeoPool RX"
|
||||
#define D_SENSOR_VL53L0X_XSHUT "VL53L0X XSHUT"
|
||||
#define D_NEW_ADDRESS "Setting address to"
|
||||
#define D_OUT_OF_RANGE "Out of Range"
|
||||
@ -808,6 +811,9 @@
|
||||
#define D_SENSOR_TFMINIPLUS_TX "TFmini+ TX"
|
||||
#define D_SENSOR_TFMINIPLUS_RX "TFmini+ RX"
|
||||
|
||||
#define D_NEW_ADDRESS "Positionner l'adresse à"
|
||||
#define D_OUT_OF_RANGE "Hors limites"
|
||||
#define D_SENSOR_DETECTED "détecté"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
@ -855,8 +861,8 @@
|
||||
#define D_UNIT_WATTHOUR "Wh"
|
||||
#define D_UNIT_WATT_METER_QUADRAT "W/m²"
|
||||
//SDM220, SDM120, SDM72, LE01MR
|
||||
#define D_EXPORT_POWER "Export Power"
|
||||
#define D_IMPORT_POWER "Import Power"
|
||||
#define D_EXPORT_POWER "Puissance fournie"
|
||||
#define D_IMPORT_POWER "Puissance consommée"
|
||||
#define D_PHASE_ANGLE "Angle de phase"
|
||||
#define D_IMPORT_ACTIVE "Énergie act conso"
|
||||
#define D_EXPORT_ACTIVE "Énergie act fournie"
|
||||
@ -938,7 +944,7 @@
|
||||
#define D_SENSOR_BOILER_OT_TX "OpenTherm TX"
|
||||
|
||||
// xnrg_15_teleinfo Denky (Teleinfo)
|
||||
#define D_CONTRACT "Type contrat"
|
||||
#define D_CONTRACT "Type de contrat"
|
||||
#define D_POWER_LOAD "Charge actuelle"
|
||||
#define D_CURRENT_TARIFF "Tarif en cours"
|
||||
#define D_TARIFF "Tarif"
|
||||
@ -964,7 +970,7 @@
|
||||
#define D_FP_FEATUREFAIL "Empreinte trop petite" // 0x07 Failed to generate character file due to the lack of character point or small fingerprint image
|
||||
#define D_FP_NOMATCH "Le doigt ne correspond pas" // 0x08 Finger doesn't match
|
||||
#define D_FP_NOTFOUND "Pas de doigt correspondant" // 0x09 Failed to find matching finger
|
||||
#define D_FP_ENROLLMISMATCH "Echec de la comparaison" // 0x0A Failed to combine the character files
|
||||
#define D_FP_ENROLLMISMATCH "Échec de la comparaison" // 0x0A Failed to combine the character files
|
||||
#define D_FP_BADLOCATION "Erreur d'indexation" // 0x0B Addressed PageID is beyond the finger library
|
||||
#define D_FP_DBRANGEFAIL "Modèle invalide" // 0x0C Error when reading template from library or invalid template
|
||||
#define D_FP_UPLOADFEATUREFAIL "Erreur de transfert" // 0x0D Error when uploading template
|
||||
@ -993,43 +999,43 @@
|
||||
#define D_NEOPOOL_MACH_GENERIC "Generic"
|
||||
#define D_NEOPOOL_MACH_BAYROL "Bayrol"
|
||||
#define D_NEOPOOL_MACH_HAY "Hay"
|
||||
#define D_NEOPOOL_FILTRATION_MANUAL "Manual" // Filtration modes
|
||||
#define D_NEOPOOL_FILTRATION_MANUAL "Manuel" // Filtration modes
|
||||
#define D_NEOPOOL_FILTRATION_AUTO "Auto"
|
||||
#define D_NEOPOOL_FILTRATION_HEATING "Heating"
|
||||
#define D_NEOPOOL_FILTRATION_SMART "Smart"
|
||||
#define D_NEOPOOL_FILTRATION_HEATING "Chauffage"
|
||||
#define D_NEOPOOL_FILTRATION_SMART "Malin"
|
||||
#define D_NEOPOOL_FILTRATION_INTELLIGENT "Intelligent"
|
||||
#define D_NEOPOOL_FILTRATION_BACKWASH "Backwash"
|
||||
#define D_NEOPOOL_FILTRATION_BACKWASH "Rétro-lavage"
|
||||
#define D_NEOPOOL_FILTRATION_NONE "" // Filtration speed level
|
||||
#define D_NEOPOOL_FILTRATION_SLOW "slow"
|
||||
#define D_NEOPOOL_FILTRATION_MEDIUM "medium"
|
||||
#define D_NEOPOOL_FILTRATION_FAST "fast"
|
||||
#define D_NEOPOOL_FILTRATION_SLOW "lent"
|
||||
#define D_NEOPOOL_FILTRATION_MEDIUM "moyen"
|
||||
#define D_NEOPOOL_FILTRATION_FAST "rapide"
|
||||
#define D_NEOPOOL_TYPE "Type" // Sensor & relais names
|
||||
#define D_NEOPOOL_REDOX "Redox"
|
||||
#define D_NEOPOOL_CHLORINE "Chlorine"
|
||||
#define D_NEOPOOL_CONDUCTIVITY "Conductivity"
|
||||
#define D_NEOPOOL_IONIZATION "Ionization"
|
||||
#define D_NEOPOOL_HYDROLYSIS "Hydrolysis"
|
||||
#define D_NEOPOOL_RELAY "Relay"
|
||||
#define D_NEOPOOL_CHLORINE "Chlore"
|
||||
#define D_NEOPOOL_CONDUCTIVITY "Conductivité"
|
||||
#define D_NEOPOOL_IONIZATION "Ionisation"
|
||||
#define D_NEOPOOL_HYDROLYSIS "Hydrolyse"
|
||||
#define D_NEOPOOL_RELAY "Relais"
|
||||
#define D_NEOPOOL_RELAY_FILTRATION "Filtration"
|
||||
#define D_NEOPOOL_RELAY_LIGHT "Light"
|
||||
#define D_NEOPOOL_RELAY_PH_ACID "Acid pump"
|
||||
#define D_NEOPOOL_RELAY_PH_BASE "Base pump"
|
||||
#define D_NEOPOOL_RELAY_RX "Redox level"
|
||||
#define D_NEOPOOL_RELAY_CL "Chlorine pump"
|
||||
#define D_NEOPOOL_RELAY_CD "Brine pump"
|
||||
#define D_NEOPOOL_TIME "Time"
|
||||
#define D_NEOPOOL_RELAY_LIGHT "Lumière"
|
||||
#define D_NEOPOOL_RELAY_PH_ACID "Pompe acide"
|
||||
#define D_NEOPOOL_RELAY_PH_BASE "Pompe base"
|
||||
#define D_NEOPOOL_RELAY_RX "Pompe RedOx"
|
||||
#define D_NEOPOOL_RELAY_CL "Pompe Chlore"
|
||||
#define D_NEOPOOL_RELAY_CD "Pompe Brome"
|
||||
#define D_NEOPOOL_TIME "Durée"
|
||||
#define D_NEOPOOL_FILT_MODE "Filtration"
|
||||
#define D_NEOPOOL_POLARIZATION "Pol" // Sensor status
|
||||
#define D_NEOPOOL_PR_OFF "PrOff"
|
||||
#define D_NEOPOOL_SETPOINT_OK "Ok"
|
||||
#define D_NEOPOOL_COVER "Cover"
|
||||
#define D_NEOPOOL_SHOCK "Shock"
|
||||
#define D_NEOPOOL_SETPOINT_OK "OK"
|
||||
#define D_NEOPOOL_COVER "Couverture"
|
||||
#define D_NEOPOOL_SHOCK "Choc chlore"
|
||||
#define D_NEOPOOL_ALARM "! "
|
||||
#define D_NEOPOOL_LOW "Low"
|
||||
#define D_NEOPOOL_LOW "Bas"
|
||||
#define D_NEOPOOL_FLOW1 "FL1"
|
||||
#define D_NEOPOOL_FLOW2 "FL2"
|
||||
#define D_NEOPOOL_PH_HIGH "too high" // ph Alarms
|
||||
#define D_NEOPOOL_PH_LOW "too low"
|
||||
#define D_NEOPOOL_PUMP_TIME_EXCEEDED "pump time exceeded"
|
||||
#define D_NEOPOOL_PH_HIGH "Trop haut" // ph Alarms
|
||||
#define D_NEOPOOL_PH_LOW "Trop bas"
|
||||
#define D_NEOPOOL_PUMP_TIME_EXCEEDED "durée pompage expirée"
|
||||
|
||||
#endif // _LANGUAGE_FR_FR_H_
|
||||
|
@ -647,6 +647,9 @@
|
||||
#define D_SENSOR_TM1638_CLK "TM1638 CLK"
|
||||
#define D_SENSOR_TM1638_DIO "TM1638 DIO"
|
||||
#define D_SENSOR_TM1638_STB "TM1638 STB"
|
||||
#define D_SENSOR_MAX7219_DIN "MAX7219 DIN"
|
||||
#define D_SENSOR_MAX7219_CS "MAX7219 CS"
|
||||
#define D_SENSOR_MAX7219_CLK "MAX7219 CLK"
|
||||
#define D_SENSOR_HX711_SCK "HX711 SCK"
|
||||
#define D_SENSOR_HX711_DAT "HX711 DAT"
|
||||
#define D_SENSOR_FTC532 "FTC532"
|
||||
|
@ -647,6 +647,9 @@
|
||||
#define D_SENSOR_TM1638_CLK "TM1638 CLK"
|
||||
#define D_SENSOR_TM1638_DIO "TM1638 DIO"
|
||||
#define D_SENSOR_TM1638_STB "TM1638 STB"
|
||||
#define D_SENSOR_MAX7219_DIN "MAX7219 DIN"
|
||||
#define D_SENSOR_MAX7219_CS "MAX7219 CS"
|
||||
#define D_SENSOR_MAX7219_CLK "MAX7219 CLK"
|
||||
#define D_SENSOR_HX711_SCK "HX711 SCK"
|
||||
#define D_SENSOR_HX711_DAT "HX711 DAT"
|
||||
#define D_SENSOR_FTC532 "FTC532"
|
||||
|
@ -647,6 +647,9 @@
|
||||
#define D_SENSOR_TM1638_CLK "TM1638 CLK"
|
||||
#define D_SENSOR_TM1638_DIO "TM1638 DIO"
|
||||
#define D_SENSOR_TM1638_STB "TM1638 STB"
|
||||
#define D_SENSOR_MAX7219_DIN "MAX7219 DIN"
|
||||
#define D_SENSOR_MAX7219_CS "MAX7219 CS"
|
||||
#define D_SENSOR_MAX7219_CLK "MAX7219 CLK"
|
||||
#define D_SENSOR_HX711_SCK "HX711 SCK"
|
||||
#define D_SENSOR_HX711_DAT "HX711 DAT"
|
||||
#define D_SENSOR_FTC532 "FTC532"
|
||||
|
@ -647,6 +647,9 @@
|
||||
#define D_SENSOR_TM1638_CLK "TM1638 - CLK"
|
||||
#define D_SENSOR_TM1638_DIO "TM1638 - DIO"
|
||||
#define D_SENSOR_TM1638_STB "TM1638 - STB"
|
||||
#define D_SENSOR_MAX7219_DIN "MAX7219 - DIN"
|
||||
#define D_SENSOR_MAX7219_CS "MAX7219 - CS"
|
||||
#define D_SENSOR_MAX7219_CLK "MAX7219 - CLK"
|
||||
#define D_SENSOR_HX711_SCK "HX711 - SCK"
|
||||
#define D_SENSOR_HX711_DAT "HX711 - DAT"
|
||||
#define D_SENSOR_FTC532 "FTC532"
|
||||
|
@ -647,6 +647,9 @@
|
||||
#define D_SENSOR_TM1638_CLK "TM1638 CLK"
|
||||
#define D_SENSOR_TM1638_DIO "TM1638 DIO"
|
||||
#define D_SENSOR_TM1638_STB "TM1638 STB"
|
||||
#define D_SENSOR_MAX7219_DIN "MAX7219 DIN"
|
||||
#define D_SENSOR_MAX7219_CS "MAX7219 CS"
|
||||
#define D_SENSOR_MAX7219_CLK "MAX7219 CLK"
|
||||
#define D_SENSOR_HX711_SCK "HX711 SCK"
|
||||
#define D_SENSOR_HX711_DAT "HX711 DAT"
|
||||
#define D_SENSOR_FTC532 "FTC532"
|
||||
|
@ -647,6 +647,9 @@
|
||||
#define D_SENSOR_TM1638_CLK "TM1638 CLK"
|
||||
#define D_SENSOR_TM1638_DIO "TM1638 DIO"
|
||||
#define D_SENSOR_TM1638_STB "TM1638 STB"
|
||||
#define D_SENSOR_MAX7219_DIN "MAX7219 DIN"
|
||||
#define D_SENSOR_MAX7219_CS "MAX7219 CS"
|
||||
#define D_SENSOR_MAX7219_CLK "MAX7219 CLK"
|
||||
#define D_SENSOR_HX711_SCK "HX711 SCK"
|
||||
#define D_SENSOR_HX711_DAT "HX711 DAT"
|
||||
#define D_SENSOR_FTC532 "FTC532"
|
||||
|
@ -647,6 +647,9 @@
|
||||
#define D_SENSOR_TM1638_CLK "TM1638 CLK"
|
||||
#define D_SENSOR_TM1638_DIO "TM1638 DIO"
|
||||
#define D_SENSOR_TM1638_STB "TM1638 STB"
|
||||
#define D_SENSOR_MAX7219_DIN "MAX7219 DIN"
|
||||
#define D_SENSOR_MAX7219_CS "MAX7219 CS"
|
||||
#define D_SENSOR_MAX7219_CLK "MAX7219 CLK"
|
||||
#define D_SENSOR_HX711_SCK "HX711 SCK"
|
||||
#define D_SENSOR_HX711_DAT "HX711 DAT"
|
||||
#define D_SENSOR_FTC532 "FTC532"
|
||||
|
@ -647,6 +647,9 @@
|
||||
#define D_SENSOR_TM1638_CLK "TM1638 CLK"
|
||||
#define D_SENSOR_TM1638_DIO "TM1638 DIO"
|
||||
#define D_SENSOR_TM1638_STB "TM1638 STB"
|
||||
#define D_SENSOR_MAX7219_DIN "MAX7219 DIN"
|
||||
#define D_SENSOR_MAX7219_CS "MAX7219 CS"
|
||||
#define D_SENSOR_MAX7219_CLK "MAX7219 CLK"
|
||||
#define D_SENSOR_HX711_SCK "HX711 SCK"
|
||||
#define D_SENSOR_HX711_DAT "HX711 DAT"
|
||||
#define D_SENSOR_FTC532 "FTC532"
|
||||
|
@ -647,6 +647,9 @@
|
||||
#define D_SENSOR_TM1638_CLK "TM1638 CLK"
|
||||
#define D_SENSOR_TM1638_DIO "TM1638 DIO"
|
||||
#define D_SENSOR_TM1638_STB "TM1638 STB"
|
||||
#define D_SENSOR_MAX7219_DIN "MAX7219 DIN"
|
||||
#define D_SENSOR_MAX7219_CS "MAX7219 CS"
|
||||
#define D_SENSOR_MAX7219_CLK "MAX7219 CLK"
|
||||
#define D_SENSOR_HX711_SCK "HX711 SCK"
|
||||
#define D_SENSOR_HX711_DAT "HX711 DAT"
|
||||
#define D_SENSOR_FTC532 "FTC532"
|
||||
|
@ -647,6 +647,9 @@
|
||||
#define D_SENSOR_TM1638_CLK "TM1638 CLK"
|
||||
#define D_SENSOR_TM1638_DIO "TM1638 DIO"
|
||||
#define D_SENSOR_TM1638_STB "TM1638 STB"
|
||||
#define D_SENSOR_MAX7219_DIN "MAX7219 DIN"
|
||||
#define D_SENSOR_MAX7219_CS "MAX7219 CS"
|
||||
#define D_SENSOR_MAX7219_CLK "MAX7219 CLK"
|
||||
#define D_SENSOR_HX711_SCK "HX711 SCK"
|
||||
#define D_SENSOR_HX711_DAT "HX711 DAT"
|
||||
#define D_SENSOR_FTC532 "FTC532"
|
||||
|
@ -647,6 +647,9 @@
|
||||
#define D_SENSOR_TM1638_CLK "TM1638 CLK"
|
||||
#define D_SENSOR_TM1638_DIO "TM1638 DIO"
|
||||
#define D_SENSOR_TM1638_STB "TM1638 STB"
|
||||
#define D_SENSOR_MAX7219_DIN "MAX7219 DIN"
|
||||
#define D_SENSOR_MAX7219_CS "MAX7219 CS"
|
||||
#define D_SENSOR_MAX7219_CLK "MAX7219 CLK"
|
||||
#define D_SENSOR_HX711_SCK "HX711 SCK"
|
||||
#define D_SENSOR_HX711_DAT "HX711 DAT"
|
||||
#define D_SENSOR_FTC532 "FTC532"
|
||||
|
@ -647,6 +647,9 @@
|
||||
#define D_SENSOR_TM1638_CLK "TM1638 CLK"
|
||||
#define D_SENSOR_TM1638_DIO "TM1638 DIO"
|
||||
#define D_SENSOR_TM1638_STB "TM1638 STB"
|
||||
#define D_SENSOR_MAX7219_DIN "MAX7219 DIN"
|
||||
#define D_SENSOR_MAX7219_CS "MAX7219 CS"
|
||||
#define D_SENSOR_MAX7219_CLK "MAX7219 CLK"
|
||||
#define D_SENSOR_HX711_SCK "HX711 SCK"
|
||||
#define D_SENSOR_HX711_DAT "HX711 DAT"
|
||||
#define D_SENSOR_FTC532 "FTC532"
|
||||
|
@ -647,6 +647,9 @@
|
||||
#define D_SENSOR_TM1638_CLK "TM1638 CLK"
|
||||
#define D_SENSOR_TM1638_DIO "TM1638 DIO"
|
||||
#define D_SENSOR_TM1638_STB "TM1638 STB"
|
||||
#define D_SENSOR_MAX7219_DIN "MAX7219 DIN"
|
||||
#define D_SENSOR_MAX7219_CS "MAX7219 CS"
|
||||
#define D_SENSOR_MAX7219_CLK "MAX7219 CLK"
|
||||
#define D_SENSOR_HX711_SCK "HX711 SCK"
|
||||
#define D_SENSOR_HX711_DAT "HX711 DAT"
|
||||
#define D_SENSOR_FTC532 "FTC532"
|
||||
|
@ -647,6 +647,9 @@
|
||||
#define D_SENSOR_TM1638_CLK "TM1638 CLK"
|
||||
#define D_SENSOR_TM1638_DIO "TM1638 DIO"
|
||||
#define D_SENSOR_TM1638_STB "TM1638 STB"
|
||||
#define D_SENSOR_MAX7219_DIN "MAX7219 DIN"
|
||||
#define D_SENSOR_MAX7219_CS "MAX7219 CS"
|
||||
#define D_SENSOR_MAX7219_CLK "MAX7219 CLK"
|
||||
#define D_SENSOR_HX711_SCK "HX711 SCK"
|
||||
#define D_SENSOR_HX711_DAT "HX711 DAT"
|
||||
#define D_SENSOR_FTC532 "FTC532"
|
||||
|
@ -647,6 +647,9 @@
|
||||
#define D_SENSOR_TM1638_CLK "TM1638 CLK"
|
||||
#define D_SENSOR_TM1638_DIO "TM1638 DIO"
|
||||
#define D_SENSOR_TM1638_STB "TM1638 STB"
|
||||
#define D_SENSOR_MAX7219_DIN "MAX7219 DIN"
|
||||
#define D_SENSOR_MAX7219_CS "MAX7219 CS"
|
||||
#define D_SENSOR_MAX7219_CLK "MAX7219 CLK"
|
||||
#define D_SENSOR_HX711_SCK "HX711 SCK"
|
||||
#define D_SENSOR_HX711_DAT "HX711 DAT"
|
||||
#define D_SENSOR_FTC532 "FTC532"
|
||||
|
@ -647,6 +647,9 @@
|
||||
#define D_SENSOR_TM1638_CLK "TM1638 CLK"
|
||||
#define D_SENSOR_TM1638_DIO "TM1638 DIO"
|
||||
#define D_SENSOR_TM1638_STB "TM1638 STB"
|
||||
#define D_SENSOR_MAX7219_DIN "MAX7219 DIN"
|
||||
#define D_SENSOR_MAX7219_CS "MAX7219 CS"
|
||||
#define D_SENSOR_MAX7219_CLK "MAX7219 CLK"
|
||||
#define D_SENSOR_HX711_SCK "HX711 SCK"
|
||||
#define D_SENSOR_HX711_DAT "HX711 DAT"
|
||||
#define D_SENSOR_FTC532 "FTC532"
|
||||
|
@ -647,6 +647,9 @@
|
||||
#define D_SENSOR_TM1638_CLK "TM1638 CLK"
|
||||
#define D_SENSOR_TM1638_DIO "TM1638 DIO"
|
||||
#define D_SENSOR_TM1638_STB "TM1638 STB"
|
||||
#define D_SENSOR_MAX7219_DIN "MAX7219 DIN"
|
||||
#define D_SENSOR_MAX7219_CS "MAX7219 CS"
|
||||
#define D_SENSOR_MAX7219_CLK "MAX7219 CLK"
|
||||
#define D_SENSOR_HX711_SCK "HX711 SCK"
|
||||
#define D_SENSOR_HX711_DAT "HX711 DAT"
|
||||
#define D_SENSOR_FTC532 "FTC532"
|
||||
|
@ -647,6 +647,9 @@
|
||||
#define D_SENSOR_TM1638_CLK "TM1638 CLK"
|
||||
#define D_SENSOR_TM1638_DIO "TM1638 DIO"
|
||||
#define D_SENSOR_TM1638_STB "TM1638 STB"
|
||||
#define D_SENSOR_MAX7219_DIN "MAX7219 DIN"
|
||||
#define D_SENSOR_MAX7219_CS "MAX7219 CS"
|
||||
#define D_SENSOR_MAX7219_CLK "MAX7219 CLK"
|
||||
#define D_SENSOR_HX711_SCK "HX711 SCK"
|
||||
#define D_SENSOR_HX711_DAT "HX711 DAT"
|
||||
#define D_SENSOR_FTC532 "FTC532"
|
||||
|
@ -463,6 +463,11 @@
|
||||
|
||||
// #define SUPPORT_MQTT_EVENT // Support trigger event with MQTT subscriptions (+3k5 code)
|
||||
|
||||
// -- Berry Scripting Language - ESP32 only ----------------------------
|
||||
// #define USE_BERRY // Enable Berry scripting language
|
||||
#define USE_BERRY_PSRAM // Allocate Berry memory in PSRAM if PSRAM is connected - this might be slightly slower but leaves main memory intact
|
||||
|
||||
|
||||
// -- Optional modules ----------------------------
|
||||
#define ROTARY_V1 // Add support for Rotary Encoder as used in MI Desk Lamp (+0k8 code)
|
||||
#define ROTARY_MAX_STEPS 10 // Rotary step boundary
|
||||
|
@ -149,7 +149,7 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu
|
||||
uint32_t mqtt_state_retain : 1; // bit 7 (v9.3.0.1) - CMND_STATERETAIN
|
||||
uint32_t mqtt_info_retain : 1; // bit 8 (v9.3.0.1) - CMND_INFORETAIN
|
||||
uint32_t wiegand_hex_output : 1; // bit 9 (v9.3.1.1) - SetOption123 - (Wiegand) switch tag number output to hex format (1)
|
||||
uint32_t wiegand_keypad_to_tag : 1; // bit 10 (v9.3.1.1) - SetOption124 - (Wiegand) send key pad stroke as single char (0) or one tag (ending char #) (1)
|
||||
uint32_t wiegand_keypad_to_tag : 1; // bit 10 (v9.3.1.1) - SetOption124 - (Wiegand) send key pad stroke as single char (0) or one tag (ending char #) (1)
|
||||
uint32_t zigbee_hide_bridge_topic : 1; // bit 11 (v9.3.1.1) - SetOption125 - (Zigbee) Hide bridge topic from zigbee topic (use with SetOption89) (1)
|
||||
uint32_t spare12 : 1; // bit 12
|
||||
uint32_t spare13 : 1; // bit 13
|
||||
@ -330,12 +330,12 @@ typedef struct {
|
||||
typedef union {
|
||||
uint8_t data;
|
||||
struct {
|
||||
uint8_t ilimode : 3;
|
||||
uint8_t Invert : 1;
|
||||
uint8_t spare2 : 1;
|
||||
uint8_t spare3 : 1;
|
||||
uint8_t type : 3;
|
||||
uint8_t invert : 1;
|
||||
uint8_t spare4 : 1;
|
||||
uint8_t spare5 : 1;
|
||||
uint8_t spare6 : 1;
|
||||
uint8_t spare7 : 1;
|
||||
};
|
||||
} DisplayOptions;
|
||||
|
||||
|
@ -74,6 +74,10 @@ void *special_malloc(uint32_t size) {
|
||||
return malloc(size);
|
||||
}
|
||||
|
||||
void *special_realloc(void *ptr, size_t size) {
|
||||
return realloc(ptr, size);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*********************************************************************************************\
|
||||
@ -461,6 +465,13 @@ void *special_malloc(uint32_t size) {
|
||||
return malloc(size);
|
||||
}
|
||||
}
|
||||
void *special_realloc(void *ptr, size_t size) {
|
||||
if (psramFound()) {
|
||||
return heap_caps_realloc(ptr, size, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
|
||||
} else {
|
||||
return realloc(ptr, size);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // ESP32
|
||||
|
||||
|
@ -556,18 +556,22 @@ void ExecuteCommandPower(uint32_t device, uint32_t state, uint32_t source)
|
||||
((POWER_ON == state) || ((POWER_TOGGLE == state) && !(TasmotaGlobal.power & mask)))
|
||||
) {
|
||||
interlock_mutex = true; // Clear all but masked relay in interlock group if new set requested
|
||||
bool perform_interlock_delay = false;
|
||||
for (uint32_t i = 0; i < MAX_INTERLOCKS; i++) {
|
||||
if (Settings.interlock[i] & mask) { // Find interlock group
|
||||
for (uint32_t j = 0; j < TasmotaGlobal.devices_present; j++) {
|
||||
power_t imask = 1 << j;
|
||||
if ((Settings.interlock[i] & imask) && (TasmotaGlobal.power & imask) && (mask != imask)) {
|
||||
ExecuteCommandPower(j +1, POWER_OFF, SRC_IGNORE);
|
||||
delay(50); // Add some delay to make sure never have more than one relay on
|
||||
perform_interlock_delay = true;
|
||||
}
|
||||
}
|
||||
break; // An interlocked relay is only present in one group so quit
|
||||
}
|
||||
}
|
||||
if (perform_interlock_delay) {
|
||||
delay(50); // Add some delay to make sure never have more than one relay on
|
||||
}
|
||||
interlock_mutex = false;
|
||||
}
|
||||
|
||||
|
@ -307,6 +307,7 @@
|
||||
|
||||
#define USE_DISPLAY // Add Display Support (+2k code)
|
||||
#define USE_DISPLAY_TM1637 // [DisplayModel 15] Enable TM1637 module
|
||||
#define USE_DISPLAY_MAX7219 // [DisplayModel 16] Enable MAX7219 7-segment module
|
||||
|
||||
#define USE_I2C // I2C using library wire (+10k code, 0k2 mem, 124 iram)
|
||||
#define USE_DISPLAY_MODES1TO5 // Enable display mode 1 to 5 in addition to mode 0
|
||||
|
@ -55,6 +55,10 @@
|
||||
#define USE_UFILESYS
|
||||
#define USE_SDCARD
|
||||
#define GUI_TRASH_FILE
|
||||
|
||||
#define USE_BERRY // Enable Berry scripting language
|
||||
#define USE_BERRY_PSRAM // Allocate Berry memory in PSRAM if PSRAM is connected - this might be slightly slower but leaves main memory intact
|
||||
|
||||
#define USE_ADC
|
||||
#define USE_SPI
|
||||
#define USE_DISPLAY // Add SPI Display Support (+2k code)
|
||||
@ -84,6 +88,10 @@
|
||||
#define USE_UFILESYS
|
||||
#define USE_SDCARD
|
||||
#define GUI_TRASH_FILE
|
||||
|
||||
#define USE_BERRY // Enable Berry scripting language
|
||||
#define USE_BERRY_PSRAM // Allocate Berry memory in PSRAM if PSRAM is connected - this might be slightly slower but leaves main memory intact
|
||||
|
||||
#define USE_I2C
|
||||
#define USE_BMA423
|
||||
#define USE_MPU6886
|
||||
|
@ -156,6 +156,7 @@ enum UserSelectablePins {
|
||||
GPIO_CSE7761_TX, GPIO_CSE7761_RX, // CSE7761 Serial interface (Dual R3)
|
||||
GPIO_VL53L0X_XSHUT1, // VL53L0X_XSHUT (the max number of sensors is VL53L0X_MAX_SENSORS)- Used when connecting multiple VL53L0X
|
||||
GPIO_TFMINIPLUS_TX, GPIO_TFMINIPLUS_RX, // TFmini Plus ToF sensor
|
||||
GPIO_MAX7219CLK, GPIO_MAX7219DIN, GPIO_MAX7219CS, // MAX7219 interface
|
||||
GPIO_SENSOR_END };
|
||||
|
||||
enum ProgramSelectablePins {
|
||||
@ -332,9 +333,13 @@ const char kSensorNames[] PROGMEM =
|
||||
D_SENSOR_CSE7761_TX "|" D_SENSOR_CSE7761_RX "|"
|
||||
<<<<<<< HEAD
|
||||
D_SENSOR_VL53L0X_XSHUT "|"
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
>>>>>>> TFmini+
|
||||
D_SENSOR_TFMINIPLUS_TX "|" D_SENSOR_TFMINIPLUS_RX "|"
|
||||
=======
|
||||
D_SENSOR_MAX7219_CLK "|" D_SENSOR_MAX7219_DIN "|" D_SENSOR_MAX7219_CS "|"
|
||||
>>>>>>> upstream/development
|
||||
;
|
||||
|
||||
const char kSensorNamesFixed[] PROGMEM =
|
||||
@ -798,8 +803,13 @@ const uint16_t kGpioNiceList[] PROGMEM = {
|
||||
#endif
|
||||
#ifdef USE_VL53L0X
|
||||
AGPIO(GPIO_VL53L0X_XSHUT1) + VL53L0X_MAX_SENSORS, // When using multiple VL53L0X.
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef USE_DISPLAY_MAX7219
|
||||
AGPIO(GPIO_MAX7219CLK),
|
||||
AGPIO(GPIO_MAX7219DIN),
|
||||
AGPIO(GPIO_MAX7219CS),
|
||||
#endif // USE_DISPLAY_MAX7219
|
||||
/*-------------------------------------------------------------------------------------------*\
|
||||
* ESP32 specifics
|
||||
\*-------------------------------------------------------------------------------------------*/
|
||||
|
@ -214,12 +214,15 @@ const char HTTP_HEAD_STYLE3[] PROGMEM =
|
||||
"<div style='text-align:center;color:#%06x;'><h3>" D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "</h3></div>" // COLOR_TEXT_WARNING
|
||||
#endif
|
||||
"<div style='text-align:center;color:#%06x;'><noscript>" D_NOSCRIPT "<br></noscript>" // COLOR_TITLE
|
||||
/*
|
||||
#ifdef LANGUAGE_MODULE_NAME
|
||||
"<h3>" D_MODULE " %s</h3>"
|
||||
#else
|
||||
"<h3>%s " D_MODULE "</h3>"
|
||||
#endif
|
||||
"<h2>%s</h2>";
|
||||
*/
|
||||
"<h3>%s</h3>" // Module name
|
||||
"<h2>%s</h2>"; // Device name
|
||||
|
||||
const char HTTP_MSG_SLIDER_GRADIENT[] PROGMEM =
|
||||
"<div id='%s' class='r' style='background-image:linear-gradient(to right,%s,%s);'>"
|
||||
|
@ -36,15 +36,16 @@
|
||||
#define D_CMND_POWERCAL "PowerCal"
|
||||
#define D_CMND_VOLTAGECAL "VoltageCal"
|
||||
#define D_CMND_CURRENTCAL "CurrentCal"
|
||||
#define D_CMND_FREQUENCYCAL "FrequencyCal"
|
||||
#define D_CMND_TARIFF "Tariff"
|
||||
#define D_CMND_MODULEADDRESS "ModuleAddress"
|
||||
|
||||
enum EnergyCommands {
|
||||
CMND_POWERCAL, CMND_VOLTAGECAL, CMND_CURRENTCAL,
|
||||
CMND_POWERCAL, CMND_VOLTAGECAL, CMND_CURRENTCAL, CMND_FREQUENCYCAL,
|
||||
CMND_POWERSET, CMND_VOLTAGESET, CMND_CURRENTSET, CMND_FREQUENCYSET, CMND_MODULEADDRESS };
|
||||
|
||||
const char kEnergyCommands[] PROGMEM = "|" // No prefix
|
||||
D_CMND_POWERCAL "|" D_CMND_VOLTAGECAL "|" D_CMND_CURRENTCAL "|"
|
||||
D_CMND_POWERCAL "|" D_CMND_VOLTAGECAL "|" D_CMND_CURRENTCAL "|" D_CMND_FREQUENCYCAL "|"
|
||||
D_CMND_POWERSET "|" D_CMND_VOLTAGESET "|" D_CMND_CURRENTSET "|" D_CMND_FREQUENCYSET "|" D_CMND_MODULEADDRESS "|"
|
||||
#ifdef USE_ENERGY_MARGIN_DETECTION
|
||||
D_CMND_POWERDELTA "|" D_CMND_POWERLOW "|" D_CMND_POWERHIGH "|" D_CMND_VOLTAGELOW "|" D_CMND_VOLTAGEHIGH "|" D_CMND_CURRENTLOW "|" D_CMND_CURRENTHIGH "|"
|
||||
@ -57,7 +58,7 @@ const char kEnergyCommands[] PROGMEM = "|" // No prefix
|
||||
D_CMND_ENERGYRESET "|" D_CMND_TARIFF ;
|
||||
|
||||
void (* const EnergyCommand[])(void) PROGMEM = {
|
||||
&CmndPowerCal, &CmndVoltageCal, &CmndCurrentCal,
|
||||
&CmndPowerCal, &CmndVoltageCal, &CmndCurrentCal, &CmndFrequencyCal,
|
||||
&CmndPowerSet, &CmndVoltageSet, &CmndCurrentSet, &CmndFrequencySet, &CmndModuleAddress,
|
||||
#ifdef USE_ENERGY_MARGIN_DETECTION
|
||||
&CmndPowerDelta, &CmndPowerLow, &CmndPowerHigh, &CmndVoltageLow, &CmndVoltageHigh, &CmndCurrentLow, &CmndCurrentHigh,
|
||||
@ -547,14 +548,12 @@ void EnergyEverySecond(void)
|
||||
* Commands
|
||||
\*********************************************************************************************/
|
||||
|
||||
void EnergyCommandCalResponse(uint32_t nvalue)
|
||||
{
|
||||
void EnergyCommandCalResponse(uint32_t nvalue) {
|
||||
snprintf_P(XdrvMailbox.command, CMDSZ, PSTR("%sCal"), XdrvMailbox.command);
|
||||
ResponseCmndNumber(nvalue);
|
||||
}
|
||||
|
||||
void CmndEnergyReset(void)
|
||||
{
|
||||
void CmndEnergyReset(void) {
|
||||
uint32_t values[2] = { 0 };
|
||||
uint32_t params = ParseParameters(2, values);
|
||||
values[0] *= 100;
|
||||
@ -641,8 +640,7 @@ void CmndEnergyReset(void)
|
||||
Settings.flag2.energy_resolution, &return2_kWhtotal);
|
||||
}
|
||||
|
||||
void CmndTariff(void)
|
||||
{
|
||||
void CmndTariff(void) {
|
||||
// Tariff1 22:00,23:00 - Tariff1 start hour for Standard Time and Daylight Savings Time
|
||||
// Tariff2 6:00,7:00 - Tariff2 start hour for Standard Time and Daylight Savings Time
|
||||
// Tariffx 1320, 1380 = minutes and also 22:00, 23:00
|
||||
@ -686,11 +684,9 @@ void CmndTariff(void)
|
||||
GetStateText(Settings.flag3.energy_weekend)); // CMND_TARIFF
|
||||
}
|
||||
|
||||
void CmndPowerCal(void)
|
||||
{
|
||||
void CmndPowerCal(void) {
|
||||
Energy.command_code = CMND_POWERCAL;
|
||||
if (XnrgCall(FUNC_COMMAND)) { // microseconds
|
||||
// if ((XdrvMailbox.payload > 999) && (XdrvMailbox.payload < 32001)) {
|
||||
if (XdrvMailbox.payload > 999) {
|
||||
Settings.energy_power_calibration = XdrvMailbox.payload;
|
||||
}
|
||||
@ -698,11 +694,9 @@ void CmndPowerCal(void)
|
||||
}
|
||||
}
|
||||
|
||||
void CmndVoltageCal(void)
|
||||
{
|
||||
void CmndVoltageCal(void) {
|
||||
Energy.command_code = CMND_VOLTAGECAL;
|
||||
if (XnrgCall(FUNC_COMMAND)) { // microseconds
|
||||
// if ((XdrvMailbox.payload > 999) && (XdrvMailbox.payload < 32001)) {
|
||||
if (XdrvMailbox.payload > 999) {
|
||||
Settings.energy_voltage_calibration = XdrvMailbox.payload;
|
||||
}
|
||||
@ -710,11 +704,9 @@ void CmndVoltageCal(void)
|
||||
}
|
||||
}
|
||||
|
||||
void CmndCurrentCal(void)
|
||||
{
|
||||
void CmndCurrentCal(void) {
|
||||
Energy.command_code = CMND_CURRENTCAL;
|
||||
if (XnrgCall(FUNC_COMMAND)) { // microseconds
|
||||
// if ((XdrvMailbox.payload > 999) && (XdrvMailbox.payload < 32001)) {
|
||||
if (XdrvMailbox.payload > 999) {
|
||||
Settings.energy_current_calibration = XdrvMailbox.payload;
|
||||
}
|
||||
@ -722,40 +714,45 @@ void CmndCurrentCal(void)
|
||||
}
|
||||
}
|
||||
|
||||
void CmndPowerSet(void)
|
||||
{
|
||||
void CmndFrequencyCal(void) {
|
||||
Energy.command_code = CMND_FREQUENCYCAL;
|
||||
if (XnrgCall(FUNC_COMMAND)) { // microseconds
|
||||
if (XdrvMailbox.payload > 999) {
|
||||
Settings.energy_frequency_calibration = XdrvMailbox.payload;
|
||||
}
|
||||
ResponseCmndNumber(Settings.energy_frequency_calibration);
|
||||
}
|
||||
}
|
||||
|
||||
void CmndPowerSet(void) {
|
||||
Energy.command_code = CMND_POWERSET;
|
||||
if (XnrgCall(FUNC_COMMAND)) { // Watt
|
||||
EnergyCommandCalResponse(Settings.energy_power_calibration);
|
||||
}
|
||||
}
|
||||
|
||||
void CmndVoltageSet(void)
|
||||
{
|
||||
void CmndVoltageSet(void) {
|
||||
Energy.command_code = CMND_VOLTAGESET;
|
||||
if (XnrgCall(FUNC_COMMAND)) { // Volt
|
||||
EnergyCommandCalResponse(Settings.energy_voltage_calibration);
|
||||
}
|
||||
}
|
||||
|
||||
void CmndCurrentSet(void)
|
||||
{
|
||||
void CmndCurrentSet(void) {
|
||||
Energy.command_code = CMND_CURRENTSET;
|
||||
if (XnrgCall(FUNC_COMMAND)) { // milliAmpere
|
||||
EnergyCommandCalResponse(Settings.energy_current_calibration);
|
||||
}
|
||||
}
|
||||
|
||||
void CmndFrequencySet(void)
|
||||
{
|
||||
void CmndFrequencySet(void) {
|
||||
Energy.command_code = CMND_FREQUENCYSET;
|
||||
if (XnrgCall(FUNC_COMMAND)) { // Hz
|
||||
EnergyCommandCalResponse(Settings.energy_frequency_calibration);
|
||||
}
|
||||
}
|
||||
|
||||
void CmndModuleAddress(void)
|
||||
{
|
||||
void CmndModuleAddress(void) {
|
||||
if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload < 4) && (1 == Energy.phase_count)) {
|
||||
Energy.command_code = CMND_MODULEADDRESS;
|
||||
if (XnrgCall(FUNC_COMMAND)) { // Module address
|
||||
@ -765,8 +762,7 @@ void CmndModuleAddress(void)
|
||||
}
|
||||
|
||||
#ifdef USE_ENERGY_MARGIN_DETECTION
|
||||
void CmndPowerDelta(void)
|
||||
{
|
||||
void CmndPowerDelta(void) {
|
||||
if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 3)) {
|
||||
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 32000)) {
|
||||
Settings.energy_power_delta[XdrvMailbox.index -1] = XdrvMailbox.payload;
|
||||
@ -775,48 +771,42 @@ void CmndPowerDelta(void)
|
||||
}
|
||||
}
|
||||
|
||||
void CmndPowerLow(void)
|
||||
{
|
||||
void CmndPowerLow(void) {
|
||||
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) {
|
||||
Settings.energy_min_power = XdrvMailbox.payload;
|
||||
}
|
||||
ResponseCmndNumber(Settings.energy_min_power);
|
||||
}
|
||||
|
||||
void CmndPowerHigh(void)
|
||||
{
|
||||
void CmndPowerHigh(void) {
|
||||
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) {
|
||||
Settings.energy_max_power = XdrvMailbox.payload;
|
||||
}
|
||||
ResponseCmndNumber(Settings.energy_max_power);
|
||||
}
|
||||
|
||||
void CmndVoltageLow(void)
|
||||
{
|
||||
void CmndVoltageLow(void) {
|
||||
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 501)) {
|
||||
Settings.energy_min_voltage = XdrvMailbox.payload;
|
||||
}
|
||||
ResponseCmndNumber(Settings.energy_min_voltage);
|
||||
}
|
||||
|
||||
void CmndVoltageHigh(void)
|
||||
{
|
||||
void CmndVoltageHigh(void) {
|
||||
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 501)) {
|
||||
Settings.energy_max_voltage = XdrvMailbox.payload;
|
||||
}
|
||||
ResponseCmndNumber(Settings.energy_max_voltage);
|
||||
}
|
||||
|
||||
void CmndCurrentLow(void)
|
||||
{
|
||||
void CmndCurrentLow(void) {
|
||||
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 16001)) {
|
||||
Settings.energy_min_current = XdrvMailbox.payload;
|
||||
}
|
||||
ResponseCmndNumber(Settings.energy_min_current);
|
||||
}
|
||||
|
||||
void CmndCurrentHigh(void)
|
||||
{
|
||||
void CmndCurrentHigh(void) {
|
||||
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 16001)) {
|
||||
Settings.energy_max_current = XdrvMailbox.payload;
|
||||
}
|
||||
@ -824,56 +814,49 @@ void CmndCurrentHigh(void)
|
||||
}
|
||||
|
||||
#ifdef USE_ENERGY_POWER_LIMIT
|
||||
void CmndMaxPower(void)
|
||||
{
|
||||
void CmndMaxPower(void) {
|
||||
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) {
|
||||
Settings.energy_max_power_limit = XdrvMailbox.payload;
|
||||
}
|
||||
ResponseCmndNumber(Settings.energy_max_power_limit);
|
||||
}
|
||||
|
||||
void CmndMaxPowerHold(void)
|
||||
{
|
||||
void CmndMaxPowerHold(void) {
|
||||
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) {
|
||||
Settings.energy_max_power_limit_hold = (1 == XdrvMailbox.payload) ? MAX_POWER_HOLD : XdrvMailbox.payload;
|
||||
}
|
||||
ResponseCmndNumber(Settings.energy_max_power_limit_hold);
|
||||
}
|
||||
|
||||
void CmndMaxPowerWindow(void)
|
||||
{
|
||||
void CmndMaxPowerWindow(void) {
|
||||
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) {
|
||||
Settings.energy_max_power_limit_window = (1 == XdrvMailbox.payload) ? MAX_POWER_WINDOW : XdrvMailbox.payload;
|
||||
}
|
||||
ResponseCmndNumber(Settings.energy_max_power_limit_window);
|
||||
}
|
||||
|
||||
void CmndSafePower(void)
|
||||
{
|
||||
void CmndSafePower(void) {
|
||||
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) {
|
||||
Settings.energy_max_power_safe_limit = XdrvMailbox.payload;
|
||||
}
|
||||
ResponseCmndNumber(Settings.energy_max_power_safe_limit);
|
||||
}
|
||||
|
||||
void CmndSafePowerHold(void)
|
||||
{
|
||||
void CmndSafePowerHold(void) {
|
||||
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) {
|
||||
Settings.energy_max_power_safe_limit_hold = (1 == XdrvMailbox.payload) ? SAFE_POWER_HOLD : XdrvMailbox.payload;
|
||||
}
|
||||
ResponseCmndNumber(Settings.energy_max_power_safe_limit_hold);
|
||||
}
|
||||
|
||||
void CmndSafePowerWindow(void)
|
||||
{
|
||||
void CmndSafePowerWindow(void) {
|
||||
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 1440)) {
|
||||
Settings.energy_max_power_safe_limit_window = (1 == XdrvMailbox.payload) ? SAFE_POWER_WINDOW : XdrvMailbox.payload;
|
||||
}
|
||||
ResponseCmndNumber(Settings.energy_max_power_safe_limit_window);
|
||||
}
|
||||
|
||||
void CmndMaxEnergy(void)
|
||||
{
|
||||
void CmndMaxEnergy(void) {
|
||||
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) {
|
||||
Settings.energy_max_energy = XdrvMailbox.payload;
|
||||
Energy.max_energy_state = 3;
|
||||
@ -881,8 +864,7 @@ void CmndMaxEnergy(void)
|
||||
ResponseCmndNumber(Settings.energy_max_energy);
|
||||
}
|
||||
|
||||
void CmndMaxEnergyStart(void)
|
||||
{
|
||||
void CmndMaxEnergyStart(void) {
|
||||
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 24)) {
|
||||
Settings.energy_max_energy_start = XdrvMailbox.payload;
|
||||
}
|
||||
|
@ -176,7 +176,10 @@ void IrSendInit(void)
|
||||
\*********************************************************************************************/
|
||||
|
||||
const bool IR_RCV_SAVE_BUFFER = false; // false = do not use buffer, true = use buffer for decoding
|
||||
const uint32_t IR_TIME_AVOID_DUPLICATE = 500; // Milliseconds
|
||||
|
||||
#ifndef IR_TIME_AVOID_DUPLICATE
|
||||
#define IR_TIME_AVOID_DUPLICATE 50 // Milliseconds
|
||||
#endif // IR_TIME_AVOID_DUPLICATE
|
||||
|
||||
#include <IRrecv.h>
|
||||
|
||||
|
@ -167,7 +167,10 @@ uint64_t reverseBitsInBytes64(uint64_t b) {
|
||||
\*********************************************************************************************/
|
||||
|
||||
const bool IR_FULL_RCV_SAVE_BUFFER = false; // false = do not use buffer, true = use buffer for decoding
|
||||
const uint32_t IR_TIME_AVOID_DUPLICATE = 50; // Milliseconds
|
||||
|
||||
#ifndef IR_TIME_AVOID_DUPLICATE
|
||||
#define IR_TIME_AVOID_DUPLICATE 50 // Milliseconds
|
||||
#endif // IR_TIME_AVOID_DUPLICATE
|
||||
|
||||
// Below is from IRrecvDumpV2.ino
|
||||
// As this program is a special purpose capture/decoder, let us use a larger
|
||||
|
@ -67,8 +67,8 @@ keywords if then else endif, or, and are better readable for beginners (others m
|
||||
|
||||
#define MAX_SARRAY_NUM 32
|
||||
|
||||
//uint32_t EncodeLightId(uint8_t relay_id);
|
||||
//uint32_t DecodeLightId(uint32_t hue_id);
|
||||
uint32_t EncodeLightId(uint8_t relay_id);
|
||||
uint32_t DecodeLightId(uint32_t hue_id);
|
||||
|
||||
#define SPECIAL_EEPMODE_SIZE 6200
|
||||
|
||||
@ -776,7 +776,7 @@ char *script;
|
||||
|
||||
script_mem_size += 16;
|
||||
uint8_t *script_mem;
|
||||
script_mem = (uint8_t*)calloc(script_mem_size, 1);
|
||||
script_mem = (uint8_t*)special_malloc(script_mem_size);
|
||||
if (!script_mem) {
|
||||
if (imemptr) free(imemptr);
|
||||
return -4;
|
||||
@ -2175,7 +2175,7 @@ chknext:
|
||||
if (ef) {
|
||||
uint16_t fsiz = ef.size();
|
||||
if (fsiz<2048) {
|
||||
char *script = (char*)calloc(fsiz + 16, 1);
|
||||
char *script = (char*)special_malloc(fsiz + 16);
|
||||
if (script) {
|
||||
ef.read((uint8_t*)script,fsiz);
|
||||
execute_script(script);
|
||||
@ -3643,15 +3643,22 @@ int32_t UpdVar(char *vname, float *fvar, uint32_t mode) {
|
||||
if (vtype == NUM_RES || (vtype & STYPE) == 0) {
|
||||
if (mode) {
|
||||
// set var
|
||||
//AddLog(LOG_LEVEL_DEBUG, PSTR("write from homekit: %s - %d"), vname, (uint32_t)res);
|
||||
index = glob_script_mem.type[ind.index].index;
|
||||
glob_script_mem.fvars[index] = res;
|
||||
glob_script_mem.type[ind.index].bits.changed = 1;
|
||||
#ifdef USE_SCRIPT_GLOBVARS
|
||||
if (glob_script_mem.type[ind.index].bits.global) {
|
||||
script_udp_sendvar(vname, &res, 0);
|
||||
}
|
||||
#endif //USE_SCRIPT_GLOBVARS
|
||||
return 0;
|
||||
} else {
|
||||
// get var
|
||||
//index = glob_script_mem.type[ind.index].index;
|
||||
int32_t ret = glob_script_mem.type[ind.index].bits.hchanged;
|
||||
glob_script_mem.type[ind.index].bits.hchanged = 0;
|
||||
//AddLog(LOG_LEVEL_DEBUG, PSTR("read from homekit: %s - %d - %d"), vname, (uint32_t)*fvar, ret);
|
||||
return ret;
|
||||
}
|
||||
} else {
|
||||
@ -6357,7 +6364,8 @@ void ScriptGetSDCard(void) {
|
||||
if (!HttpCheckPriviledgedAccess()) { return; }
|
||||
|
||||
String stmp = Webserver->uri();
|
||||
char *cp = strstr_P(stmp.c_str(), PSTR("/sdc/"));
|
||||
|
||||
char *cp = strstr_P(stmp.c_str(), PSTR("/ufs/"));
|
||||
// if (cp) Serial.printf(">>>%s\n",cp);
|
||||
if (cp) {
|
||||
#ifdef ESP32
|
||||
@ -6365,13 +6373,15 @@ void ScriptGetSDCard(void) {
|
||||
#else
|
||||
cp += 5;
|
||||
#endif
|
||||
if (strstr_P(cp, PSTR("scrdmp.bmp"))) {
|
||||
SendFile(cp);
|
||||
return;
|
||||
} else {
|
||||
if (ufsp->exists(cp)) {
|
||||
if (ufsp) {
|
||||
if (strstr_P(cp, PSTR("scrdmp.bmp"))) {
|
||||
SendFile(cp);
|
||||
return;
|
||||
} else {
|
||||
if (ufsp->exists(cp)) {
|
||||
SendFile(cp);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -6392,7 +6402,6 @@ char buff[512];
|
||||
#ifdef USE_DISPLAY_DUMP
|
||||
char *sbmp = strstr_P(fname, PSTR("scrdmp.bmp"));
|
||||
if (sbmp) {
|
||||
mime = "image/bmp";
|
||||
sflg = 1;
|
||||
}
|
||||
#endif // USE_DISPLAY_DUMP
|
||||
@ -6419,7 +6428,7 @@ char buff[512];
|
||||
#define infoHeaderSize 40
|
||||
if (buffer) {
|
||||
uint8_t *bp = buffer;
|
||||
uint8_t *lbuf = (uint8_t*)calloc(Settings.display_width + 2, 3);
|
||||
uint8_t *lbuf = (uint8_t*)special_malloc(Settings.display_width + 2);
|
||||
uint8_t *lbp;
|
||||
uint8_t fileHeader[fileHeaderSize];
|
||||
createBitmapFileHeader(Settings.display_height , Settings.display_width , fileHeader);
|
||||
@ -7679,7 +7688,7 @@ bool Xdrv10(uint8_t function)
|
||||
// we have a file system
|
||||
AddLog(LOG_LEVEL_INFO,PSTR("UFILESYSTEM OK!"));
|
||||
char *script;
|
||||
script = (char*)calloc(UFSYS_SIZE + 4, 1);
|
||||
script = (char*)special_malloc(UFSYS_SIZE + 4);
|
||||
if (!script) break;
|
||||
glob_script_mem.script_ram = script;
|
||||
glob_script_mem.script_size = UFSYS_SIZE;
|
||||
@ -7850,6 +7859,10 @@ bool Xdrv10(uint8_t function)
|
||||
Webserver->on("/sfd", ScriptFullWebpage);
|
||||
}
|
||||
#endif // SCRIPT_FULL_WEBPAGE
|
||||
|
||||
#ifdef USE_UFILESYS
|
||||
Webserver->onNotFound(ScriptGetSDCard);
|
||||
#endif // USE_UFILESYS
|
||||
}
|
||||
break;
|
||||
#endif // USE_SCRIPT_WEB_DISPLAY
|
||||
@ -7858,7 +7871,6 @@ 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);
|
||||
break;
|
||||
#endif // USE_WEBSERVER
|
||||
case FUNC_SAVE_BEFORE_RESTART:
|
||||
if (bitRead(Settings.rule_enabled, 0)) {
|
||||
|
@ -54,22 +54,24 @@ const uint8_t DISPLAY_LOG_ROWS = 32; // Number of lines in display log
|
||||
#define D_CMND_DISP_DIMMER "Dimmer"
|
||||
#define D_CMND_DISP_MODE "Mode"
|
||||
#define D_CMND_DISP_MODEL "Model"
|
||||
#define D_CMND_DISP_TYPE "Type"
|
||||
#define D_CMND_DISP_REFRESH "Refresh"
|
||||
#define D_CMND_DISP_ROWS "Rows"
|
||||
#define D_CMND_DISP_SIZE "Size"
|
||||
#define D_CMND_DISP_FONT "Font"
|
||||
#define D_CMND_DISP_ROTATE "Rotate"
|
||||
#define D_CMND_DISP_TEXT "Text"
|
||||
#define D_CMND_DISP_INVERT "Invert"
|
||||
#define D_CMND_DISP_WIDTH "Width"
|
||||
#define D_CMND_DISP_HEIGHT "Height"
|
||||
#define D_CMND_DISP_BLINKRATE "Blinkrate"
|
||||
#define D_CMND_DISP_BATCH "Batch"
|
||||
#define D_CMND_DISP_TEXT "Text"
|
||||
|
||||
#define D_CMND_DISP_CLEAR "Clear"
|
||||
#define D_CMND_DISP_NUMBER "Number"
|
||||
#define D_CMND_DISP_FLOAT "Float"
|
||||
#define D_CMND_DISP_NUMBERNC "NumberNC" // NC - "No Clear"
|
||||
#define D_CMND_DISP_FLOATNC "FloatNC" // NC - "No Clear"
|
||||
#define D_CMND_DISP_BRIGHTNESS "Brightness"
|
||||
#define D_CMND_DISP_NUMBERNC "NumberNC" // NC - "No Clear"
|
||||
#define D_CMND_DISP_FLOATNC "FloatNC" // NC - "No Clear"
|
||||
#define D_CMND_DISP_RAW "Raw"
|
||||
#define D_CMND_DISP_LEVEL "Level"
|
||||
#define D_CMND_DISP_SEVENSEG_TEXT "SevensegText"
|
||||
@ -78,9 +80,6 @@ const uint8_t DISPLAY_LOG_ROWS = 32; // Number of lines in display log
|
||||
#define D_CMND_DISP_CLOCK "Clock"
|
||||
#define D_CMND_DISP_TEXTNC "TextNC" // NC - "No Clear"
|
||||
#define D_CMND_DISP_SCROLLTEXT "ScrollText"
|
||||
#define D_CMND_DISP_ILIMODE "ILIMode"
|
||||
#define D_CMND_DISP_ILIINVERT "Invert"
|
||||
|
||||
|
||||
enum XdspFunctions { FUNC_DISPLAY_INIT_DRIVER, FUNC_DISPLAY_INIT, FUNC_DISPLAY_EVERY_50_MSECOND, FUNC_DISPLAY_EVERY_SECOND,
|
||||
FUNC_DISPLAY_MODEL, FUNC_DISPLAY_MODE, FUNC_DISPLAY_POWER,
|
||||
@ -101,31 +100,71 @@ enum XdspFunctions { FUNC_DISPLAY_INIT_DRIVER, FUNC_DISPLAY_INIT, FUNC_DISPLAY_E
|
||||
enum DisplayInitModes { DISPLAY_INIT_MODE, DISPLAY_INIT_PARTIAL, DISPLAY_INIT_FULL };
|
||||
|
||||
const char kDisplayCommands[] PROGMEM = D_PRFX_DISPLAY "|" // Prefix
|
||||
"|" D_CMND_DISP_MODEL "|" D_CMND_DISP_WIDTH "|" D_CMND_DISP_HEIGHT "|" D_CMND_DISP_MODE "|" D_CMND_DISP_REFRESH "|"
|
||||
D_CMND_DISP_DIMMER "|" D_CMND_DISP_COLS "|" D_CMND_DISP_ROWS "|" D_CMND_DISP_SIZE "|" D_CMND_DISP_FONT "|"
|
||||
D_CMND_DISP_ROTATE "|" D_CMND_DISP_TEXT "|" D_CMND_DISP_ADDRESS "|" D_CMND_DISP_BLINKRATE "|"
|
||||
"|" D_CMND_DISP_MODEL "|" D_CMND_DISP_TYPE "|" D_CMND_DISP_WIDTH "|" D_CMND_DISP_HEIGHT "|" D_CMND_DISP_MODE "|"
|
||||
D_CMND_DISP_INVERT "|" D_CMND_DISP_REFRESH "|" D_CMND_DISP_DIMMER "|" D_CMND_DISP_COLS "|" D_CMND_DISP_ROWS "|"
|
||||
D_CMND_DISP_SIZE "|" D_CMND_DISP_FONT "|" D_CMND_DISP_ROTATE "|" D_CMND_DISP_TEXT "|" D_CMND_DISP_ADDRESS "|" D_CMND_DISP_BLINKRATE "|"
|
||||
#ifdef USE_UFILESYS
|
||||
D_CMND_DISP_BATCH "|"
|
||||
#endif
|
||||
D_CMND_DISP_CLEAR "|" D_CMND_DISP_NUMBER "|" D_CMND_DISP_FLOAT "|" D_CMND_DISP_NUMBERNC "|" D_CMND_DISP_FLOATNC "|"
|
||||
D_CMND_DISP_RAW "|" D_CMND_DISP_LEVEL "|" D_CMND_DISP_SEVENSEG_TEXT "|" D_CMND_DISP_SEVENSEG_TEXTNC "|"
|
||||
D_CMND_DISP_SCROLLDELAY "|" D_CMND_DISP_CLOCK "|" D_CMND_DISP_TEXTNC "|"
|
||||
D_CMND_DISP_SCROLLTEXT "|" D_CMND_DISP_ILIMODE "|" D_CMND_DISP_ILIINVERT
|
||||
D_CMND_DISP_SCROLLDELAY "|" D_CMND_DISP_CLOCK "|" D_CMND_DISP_TEXTNC "|" D_CMND_DISP_SCROLLTEXT
|
||||
;
|
||||
|
||||
void (* const DisplayCommand[])(void) PROGMEM = {
|
||||
&CmndDisplay, &CmndDisplayModel, &CmndDisplayWidth, &CmndDisplayHeight, &CmndDisplayMode, &CmndDisplayRefresh,
|
||||
&CmndDisplayDimmer, &CmndDisplayColumns, &CmndDisplayRows, &CmndDisplaySize, &CmndDisplayFont,
|
||||
&CmndDisplayRotate, &CmndDisplayText, &CmndDisplayAddress, &CmndDisplayBlinkrate,
|
||||
&CmndDisplay, &CmndDisplayModel, &CmndDisplayType, &CmndDisplayWidth, &CmndDisplayHeight, &CmndDisplayMode,
|
||||
&CmndDisplayInvert, &CmndDisplayRefresh, &CmndDisplayDimmer, &CmndDisplayColumns, &CmndDisplayRows,
|
||||
&CmndDisplaySize, &CmndDisplayFont, &CmndDisplayRotate, &CmndDisplayText, &CmndDisplayAddress, &CmndDisplayBlinkrate,
|
||||
#ifdef USE_UFILESYS
|
||||
&CmndDisplayBatch,
|
||||
#endif
|
||||
&CmndDisplayClear, &CmndDisplayNumber, &CmndDisplayFloat, &CmndDisplayNumberNC, &CmndDisplayFloatNC,
|
||||
&CmndDisplayRaw, &CmndDisplayLevel, &CmndDisplaySevensegText, &CmndDisplaySevensegTextNC,
|
||||
&CmndDisplayScrollDelay, &CmndDisplayClock, &CmndDisplayTextNC,
|
||||
&CmndDisplayScrollText, &CmndDisplayILIMOde , &CmndDisplayILIInvert
|
||||
&CmndDisplayScrollDelay, &CmndDisplayClock, &CmndDisplayTextNC, &CmndDisplayScrollText
|
||||
};
|
||||
|
||||
#ifdef USE_GRAPH
|
||||
|
||||
typedef union {
|
||||
uint8_t data;
|
||||
struct {
|
||||
uint8_t overlay : 1;
|
||||
uint8_t draw : 1;
|
||||
uint8_t nu3 : 1;
|
||||
uint8_t nu4 : 1;
|
||||
uint8_t nu5 : 1;
|
||||
uint8_t nu6 : 1;
|
||||
uint8_t nu7 : 1;
|
||||
uint8_t nu8 : 1;
|
||||
};
|
||||
} GFLAGS;
|
||||
|
||||
struct GRAPH {
|
||||
uint16_t xp;
|
||||
uint16_t yp;
|
||||
uint16_t xs;
|
||||
uint16_t ys;
|
||||
float ymin;
|
||||
float ymax;
|
||||
float range;
|
||||
uint32_t x_time; // time per x slice in milliseconds
|
||||
uint32_t last_ms;
|
||||
uint32_t last_ms_redrawn;
|
||||
int16_t decimation; // decimation or graph duration in minutes
|
||||
uint16_t dcnt;
|
||||
uint32_t summ;
|
||||
uint16_t xcnt;
|
||||
uint8_t *values;
|
||||
uint8_t xticks;
|
||||
uint8_t yticks;
|
||||
uint8_t last_val;
|
||||
uint8_t color_index;
|
||||
GFLAGS flags;
|
||||
};
|
||||
|
||||
struct GRAPH *graph[NUM_GRAPHS];
|
||||
#endif // USE_GRAPH
|
||||
|
||||
char *dsp_str;
|
||||
|
||||
uint16_t dsp_x;
|
||||
@ -1637,18 +1676,16 @@ void DisplaySetPower(void)
|
||||
* Commands
|
||||
\*********************************************************************************************/
|
||||
|
||||
void CmndDisplay(void)
|
||||
{
|
||||
Response_P(PSTR("{\"" D_PRFX_DISPLAY "\":{\"" D_CMND_DISP_MODEL "\":%d,\"" D_CMND_DISP_WIDTH "\":%d,\"" D_CMND_DISP_HEIGHT "\":%d,\""
|
||||
void CmndDisplay(void) {
|
||||
Response_P(PSTR("{\"" D_PRFX_DISPLAY "\":{\"" D_CMND_DISP_MODEL "\":%d,\"" D_CMND_DISP_TYPE "\":%d,\"" D_CMND_DISP_WIDTH "\":%d,\"" D_CMND_DISP_HEIGHT "\":%d,\""
|
||||
D_CMND_DISP_MODE "\":%d,\"" D_CMND_DISP_DIMMER "\":%d,\"" D_CMND_DISP_SIZE "\":%d,\"" D_CMND_DISP_FONT "\":%d,\""
|
||||
D_CMND_DISP_ROTATE "\":%d,\"" D_CMND_DISP_REFRESH "\":%d,\"" D_CMND_DISP_COLS "\":[%d,%d],\"" D_CMND_DISP_ROWS "\":%d}}"),
|
||||
Settings.display_model, Settings.display_width, Settings.display_height,
|
||||
Settings.display_mode, ((Settings.display_dimmer * 666) / 100) +1, Settings.display_size, Settings.display_font,
|
||||
Settings.display_rotate, Settings.display_refresh, Settings.display_cols[0], Settings.display_cols[1], Settings.display_rows);
|
||||
D_CMND_DISP_ROTATE "\":%d,\"" D_CMND_DISP_INVERT "\":%d,\"" D_CMND_DISP_REFRESH "\":%d,\"" D_CMND_DISP_COLS "\":[%d,%d],\"" D_CMND_DISP_ROWS "\":%d}}"),
|
||||
Settings.display_model, Settings.display_options.type, Settings.display_width, Settings.display_height,
|
||||
Settings.display_mode, changeUIntScale(Settings.display_dimmer, 0, 15, 0, 100), Settings.display_size, Settings.display_font,
|
||||
Settings.display_rotate, Settings.display_options.invert, Settings.display_refresh, Settings.display_cols[0], Settings.display_cols[1], Settings.display_rows);
|
||||
}
|
||||
|
||||
void CmndDisplayModel(void)
|
||||
{
|
||||
void CmndDisplayModel(void) {
|
||||
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < DISPLAY_MAX_DRIVERS)) {
|
||||
uint32_t last_display_model = Settings.display_model;
|
||||
Settings.display_model = XdrvMailbox.payload;
|
||||
@ -1661,8 +1698,15 @@ void CmndDisplayModel(void)
|
||||
ResponseCmndNumber(Settings.display_model);
|
||||
}
|
||||
|
||||
void CmndDisplayWidth(void)
|
||||
{
|
||||
void CmndDisplayType(void) {
|
||||
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 7)) {
|
||||
Settings.display_options.type = XdrvMailbox.payload;
|
||||
TasmotaGlobal.restart_flag = 2;
|
||||
}
|
||||
ResponseCmndNumber(Settings.display_options.type);
|
||||
}
|
||||
|
||||
void CmndDisplayWidth(void) {
|
||||
if (XdrvMailbox.payload > 0) {
|
||||
if (XdrvMailbox.payload != Settings.display_width) {
|
||||
Settings.display_width = XdrvMailbox.payload;
|
||||
@ -1672,8 +1716,7 @@ void CmndDisplayWidth(void)
|
||||
ResponseCmndNumber(Settings.display_width);
|
||||
}
|
||||
|
||||
void CmndDisplayHeight(void)
|
||||
{
|
||||
void CmndDisplayHeight(void) {
|
||||
if (XdrvMailbox.payload > 0) {
|
||||
if (XdrvMailbox.payload != Settings.display_height) {
|
||||
Settings.display_height = XdrvMailbox.payload;
|
||||
@ -1683,8 +1726,7 @@ void CmndDisplayHeight(void)
|
||||
ResponseCmndNumber(Settings.display_height);
|
||||
}
|
||||
|
||||
void CmndDisplayMode(void)
|
||||
{
|
||||
void CmndDisplayMode(void) {
|
||||
#ifdef USE_DISPLAY_MODES1TO5
|
||||
/* Matrix / 7-segment LCD / Oled TFT
|
||||
* 1 = Text up and time Time
|
||||
@ -1716,7 +1758,7 @@ void CmndDisplayMode(void)
|
||||
|
||||
void CmndDisplayDimmer(void) {
|
||||
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 100)) {
|
||||
Settings.display_dimmer = ((XdrvMailbox.payload +1) * 100) / 666; // Correction for Domoticz (0 - 15)
|
||||
Settings.display_dimmer = changeUIntScale(XdrvMailbox.payload, 0, 100, 0, 15); // Correction for Domoticz (0 - 15)
|
||||
if (Settings.display_dimmer && !(disp_power)) {
|
||||
ExecuteCommandPower(disp_device, POWER_ON, SRC_DISPLAY);
|
||||
}
|
||||
@ -1729,146 +1771,11 @@ void CmndDisplayDimmer(void) {
|
||||
XdspCall(FUNC_DISPLAY_DIM);
|
||||
}
|
||||
}
|
||||
ResponseCmndNumber(((Settings.display_dimmer * 666) / 100) +1);
|
||||
ResponseCmndNumber(changeUIntScale(Settings.display_dimmer, 0, 15, 0, 100));
|
||||
}
|
||||
|
||||
void CmndDisplayBlinkrate(void)
|
||||
{
|
||||
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 3)) {
|
||||
|
||||
if (!renderer)
|
||||
XdspCall(FUNC_DISPLAY_BLINKRATE);
|
||||
}
|
||||
ResponseCmndNumber(XdrvMailbox.payload);
|
||||
}
|
||||
|
||||
|
||||
#ifdef USE_UFILESYS
|
||||
void CmndDisplayBatch(void) {
|
||||
if (XdrvMailbox.data_len > 0) {
|
||||
if (!Settings.display_mode) {
|
||||
Display_Text_From_File(XdrvMailbox.data);
|
||||
}
|
||||
ResponseCmndChar(XdrvMailbox.data);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void CmndDisplayClear(void)
|
||||
{
|
||||
if (!renderer)
|
||||
XdspCall(FUNC_DISPLAY_CLEAR);
|
||||
ResponseCmndChar(XdrvMailbox.data);
|
||||
}
|
||||
|
||||
void CmndDisplayNumber(void)
|
||||
{
|
||||
if (!renderer) {
|
||||
XdspCall(FUNC_DISPLAY_NUMBER);
|
||||
}
|
||||
ResponseCmndChar(XdrvMailbox.data);
|
||||
}
|
||||
|
||||
void CmndDisplayFloat(void)
|
||||
{
|
||||
if (!renderer) {
|
||||
XdspCall(FUNC_DISPLAY_FLOAT);
|
||||
}
|
||||
ResponseCmndChar(XdrvMailbox.data);
|
||||
}
|
||||
|
||||
void CmndDisplayNumberNC(void)
|
||||
{
|
||||
if (!renderer) {
|
||||
XdspCall(FUNC_DISPLAY_NUMBERNC);
|
||||
}
|
||||
ResponseCmndChar(XdrvMailbox.data);
|
||||
}
|
||||
|
||||
void CmndDisplayFloatNC(void)
|
||||
{
|
||||
if (!renderer) {
|
||||
XdspCall(FUNC_DISPLAY_FLOATNC);
|
||||
}
|
||||
ResponseCmndChar(XdrvMailbox.data);
|
||||
}
|
||||
|
||||
void CmndDisplayRaw(void)
|
||||
{
|
||||
if (!renderer) {
|
||||
XdspCall(FUNC_DISPLAY_RAW);
|
||||
}
|
||||
ResponseCmndChar(XdrvMailbox.data);
|
||||
}
|
||||
|
||||
void CmndDisplayLevel(void)
|
||||
{
|
||||
bool result = false;
|
||||
if (!renderer) {
|
||||
result = XdspCall(FUNC_DISPLAY_LEVEL);
|
||||
}
|
||||
if(result) ResponseCmndNumber(XdrvMailbox.payload);
|
||||
}
|
||||
|
||||
void CmndDisplaySevensegText(void)
|
||||
{
|
||||
if (!renderer) {
|
||||
XdspCall(FUNC_DISPLAY_SEVENSEG_TEXT);
|
||||
}
|
||||
ResponseCmndChar(XdrvMailbox.data);
|
||||
}
|
||||
|
||||
void CmndDisplayTextNC(void)
|
||||
{
|
||||
if (!renderer) {
|
||||
XdspCall(FUNC_DISPLAY_SEVENSEG_TEXTNC);
|
||||
}
|
||||
ResponseCmndChar(XdrvMailbox.data);
|
||||
}
|
||||
|
||||
void CmndDisplaySevensegTextNC(void)
|
||||
{
|
||||
if (!renderer) {
|
||||
XdspCall(FUNC_DISPLAY_SEVENSEG_TEXTNC);
|
||||
}
|
||||
ResponseCmndChar(XdrvMailbox.data);
|
||||
}
|
||||
|
||||
void CmndDisplayScrollDelay(void)
|
||||
{
|
||||
if (!renderer) {
|
||||
XdspCall(FUNC_DISPLAY_SCROLLDELAY);
|
||||
}
|
||||
ResponseCmndNumber(XdrvMailbox.payload);
|
||||
}
|
||||
|
||||
void CmndDisplayClock(void)
|
||||
{
|
||||
if (!renderer) {
|
||||
XdspCall(FUNC_DISPLAY_CLOCK);
|
||||
}
|
||||
ResponseCmndNumber(XdrvMailbox.payload);
|
||||
}
|
||||
|
||||
|
||||
void CmndDisplayScrollText(void)
|
||||
{
|
||||
bool result = false;
|
||||
if (!renderer) {
|
||||
result = XdspCall(FUNC_DISPLAY_SCROLLTEXT);
|
||||
}
|
||||
if(result) ResponseCmndChar(XdrvMailbox.data);
|
||||
}
|
||||
|
||||
|
||||
void CmndDisplaySize(void)
|
||||
{
|
||||
#ifdef USE_DISPLAY_TM1637
|
||||
if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= 6)) {
|
||||
#else
|
||||
void CmndDisplaySize(void) {
|
||||
if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= 4)) {
|
||||
#endif
|
||||
Settings.display_size = XdrvMailbox.payload;
|
||||
if (renderer) renderer->setTextSize(Settings.display_size);
|
||||
//else DisplaySetSize(Settings.display_size);
|
||||
@ -1876,8 +1783,7 @@ void CmndDisplaySize(void)
|
||||
ResponseCmndNumber(Settings.display_size);
|
||||
}
|
||||
|
||||
void CmndDisplayFont(void)
|
||||
{
|
||||
void CmndDisplayFont(void) {
|
||||
if ((XdrvMailbox.payload >=0) && (XdrvMailbox.payload <= 4)) {
|
||||
Settings.display_font = XdrvMailbox.payload;
|
||||
if (renderer) renderer->setTextFont(Settings.display_font);
|
||||
@ -1886,27 +1792,7 @@ void CmndDisplayFont(void)
|
||||
ResponseCmndNumber(Settings.display_font);
|
||||
}
|
||||
|
||||
|
||||
void CmndDisplayILIMOde(void)
|
||||
{
|
||||
if ((XdrvMailbox.payload >= 1) && (XdrvMailbox.payload <= 7)) {
|
||||
Settings.display_options.ilimode = XdrvMailbox.payload;
|
||||
TasmotaGlobal.restart_flag = 2;
|
||||
}
|
||||
ResponseCmndNumber(Settings.display_options.ilimode);
|
||||
}
|
||||
|
||||
void CmndDisplayILIInvert(void)
|
||||
{
|
||||
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 1)) {
|
||||
Settings.display_options.Invert = XdrvMailbox.payload;
|
||||
if (renderer) renderer->invertDisplay(Settings.display_options.Invert);
|
||||
}
|
||||
ResponseCmndNumber(Settings.display_options.Invert);
|
||||
}
|
||||
|
||||
void CmndDisplayRotate(void)
|
||||
{
|
||||
void CmndDisplayRotate(void) {
|
||||
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 4)) {
|
||||
if ((Settings.display_rotate) != XdrvMailbox.payload) {
|
||||
/*
|
||||
@ -1930,8 +1816,77 @@ void CmndDisplayRotate(void)
|
||||
ResponseCmndNumber(Settings.display_rotate);
|
||||
}
|
||||
|
||||
void CmndDisplayText(void)
|
||||
{
|
||||
void CmndDisplayInvert(void) {
|
||||
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 1)) {
|
||||
Settings.display_options.invert = XdrvMailbox.payload;
|
||||
if (renderer) renderer->invertDisplay(Settings.display_options.invert);
|
||||
}
|
||||
ResponseCmndNumber(Settings.display_options.invert);
|
||||
}
|
||||
|
||||
void CmndDisplayRefresh(void) {
|
||||
if ((XdrvMailbox.payload >= 1) && (XdrvMailbox.payload <= 7)) {
|
||||
Settings.display_refresh = XdrvMailbox.payload;
|
||||
}
|
||||
ResponseCmndNumber(Settings.display_refresh);
|
||||
}
|
||||
|
||||
void CmndDisplayColumns(void) {
|
||||
if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 2)) {
|
||||
if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= DISPLAY_MAX_COLS)) {
|
||||
Settings.display_cols[XdrvMailbox.index -1] = XdrvMailbox.payload;
|
||||
#ifdef USE_DISPLAY_MODES1TO5
|
||||
if (1 == XdrvMailbox.index) {
|
||||
DisplayLogBufferInit();
|
||||
DisplayReAllocScreenBuffer();
|
||||
}
|
||||
#endif // USE_DISPLAY_MODES1TO5
|
||||
}
|
||||
ResponseCmndIdxNumber(Settings.display_cols[XdrvMailbox.index -1]);
|
||||
}
|
||||
}
|
||||
|
||||
void CmndDisplayRows(void) {
|
||||
if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= DISPLAY_MAX_ROWS)) {
|
||||
Settings.display_rows = XdrvMailbox.payload;
|
||||
#ifdef USE_DISPLAY_MODES1TO5
|
||||
DisplayLogBufferInit();
|
||||
DisplayReAllocScreenBuffer();
|
||||
#endif // USE_DISPLAY_MODES1TO5
|
||||
}
|
||||
ResponseCmndNumber(Settings.display_rows);
|
||||
}
|
||||
|
||||
void CmndDisplayAddress(void) {
|
||||
if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 8)) {
|
||||
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 255)) {
|
||||
Settings.display_address[XdrvMailbox.index -1] = XdrvMailbox.payload;
|
||||
}
|
||||
ResponseCmndIdxNumber(Settings.display_address[XdrvMailbox.index -1]);
|
||||
}
|
||||
}
|
||||
|
||||
void CmndDisplayBlinkrate(void) {
|
||||
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 3)) {
|
||||
if (!renderer) {
|
||||
XdspCall(FUNC_DISPLAY_BLINKRATE);
|
||||
}
|
||||
}
|
||||
ResponseCmndNumber(XdrvMailbox.payload);
|
||||
}
|
||||
|
||||
#ifdef USE_UFILESYS
|
||||
void CmndDisplayBatch(void) {
|
||||
if (XdrvMailbox.data_len > 0) {
|
||||
if (!Settings.display_mode) {
|
||||
Display_Text_From_File(XdrvMailbox.data);
|
||||
}
|
||||
ResponseCmndChar(XdrvMailbox.data);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void CmndDisplayText(void) {
|
||||
if (disp_device && XdrvMailbox.data_len > 0) {
|
||||
#ifndef USE_DISPLAY_MODES1TO5
|
||||
DisplayText();
|
||||
@ -1948,50 +1903,100 @@ void CmndDisplayText(void)
|
||||
}
|
||||
}
|
||||
|
||||
void CmndDisplayAddress(void)
|
||||
{
|
||||
if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 8)) {
|
||||
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 255)) {
|
||||
Settings.display_address[XdrvMailbox.index -1] = XdrvMailbox.payload;
|
||||
}
|
||||
ResponseCmndIdxNumber(Settings.display_address[XdrvMailbox.index -1]);
|
||||
}
|
||||
/*********************************************************************************************\
|
||||
* Currently 7-segement specific - should have been handled by (extended) DisplayText command
|
||||
\*********************************************************************************************/
|
||||
|
||||
void CmndDisplayClear(void) {
|
||||
if (!renderer)
|
||||
XdspCall(FUNC_DISPLAY_CLEAR);
|
||||
ResponseCmndChar(XdrvMailbox.data);
|
||||
}
|
||||
|
||||
void CmndDisplayRefresh(void)
|
||||
{
|
||||
if ((XdrvMailbox.payload >= 1) && (XdrvMailbox.payload <= 7)) {
|
||||
Settings.display_refresh = XdrvMailbox.payload;
|
||||
void CmndDisplayNumber(void) {
|
||||
if (!renderer) {
|
||||
XdspCall(FUNC_DISPLAY_NUMBER);
|
||||
}
|
||||
ResponseCmndNumber(Settings.display_refresh);
|
||||
ResponseCmndChar(XdrvMailbox.data);
|
||||
}
|
||||
|
||||
void CmndDisplayColumns(void)
|
||||
{
|
||||
if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 2)) {
|
||||
if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= DISPLAY_MAX_COLS)) {
|
||||
Settings.display_cols[XdrvMailbox.index -1] = XdrvMailbox.payload;
|
||||
#ifdef USE_DISPLAY_MODES1TO5
|
||||
if (1 == XdrvMailbox.index) {
|
||||
DisplayLogBufferInit();
|
||||
DisplayReAllocScreenBuffer();
|
||||
}
|
||||
#endif // USE_DISPLAY_MODES1TO5
|
||||
}
|
||||
ResponseCmndIdxNumber(Settings.display_cols[XdrvMailbox.index -1]);
|
||||
void CmndDisplayFloat(void) {
|
||||
if (!renderer) {
|
||||
XdspCall(FUNC_DISPLAY_FLOAT);
|
||||
}
|
||||
ResponseCmndChar(XdrvMailbox.data);
|
||||
}
|
||||
|
||||
void CmndDisplayRows(void)
|
||||
{
|
||||
if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= DISPLAY_MAX_ROWS)) {
|
||||
Settings.display_rows = XdrvMailbox.payload;
|
||||
#ifdef USE_DISPLAY_MODES1TO5
|
||||
DisplayLogBufferInit();
|
||||
DisplayReAllocScreenBuffer();
|
||||
#endif // USE_DISPLAY_MODES1TO5
|
||||
void CmndDisplayNumberNC(void) {
|
||||
if (!renderer) {
|
||||
XdspCall(FUNC_DISPLAY_NUMBERNC);
|
||||
}
|
||||
ResponseCmndNumber(Settings.display_rows);
|
||||
ResponseCmndChar(XdrvMailbox.data);
|
||||
}
|
||||
|
||||
void CmndDisplayFloatNC(void) {
|
||||
if (!renderer) {
|
||||
XdspCall(FUNC_DISPLAY_FLOATNC);
|
||||
}
|
||||
ResponseCmndChar(XdrvMailbox.data);
|
||||
}
|
||||
|
||||
void CmndDisplayRaw(void) {
|
||||
if (!renderer) {
|
||||
XdspCall(FUNC_DISPLAY_RAW);
|
||||
}
|
||||
ResponseCmndChar(XdrvMailbox.data);
|
||||
}
|
||||
|
||||
void CmndDisplayLevel(void) {
|
||||
bool result = false;
|
||||
if (!renderer) {
|
||||
result = XdspCall(FUNC_DISPLAY_LEVEL);
|
||||
}
|
||||
if(result) ResponseCmndNumber(XdrvMailbox.payload);
|
||||
}
|
||||
|
||||
void CmndDisplaySevensegText(void) {
|
||||
if (!renderer) {
|
||||
XdspCall(FUNC_DISPLAY_SEVENSEG_TEXT);
|
||||
}
|
||||
ResponseCmndChar(XdrvMailbox.data);
|
||||
}
|
||||
|
||||
void CmndDisplayTextNC(void) {
|
||||
if (!renderer) {
|
||||
XdspCall(FUNC_DISPLAY_SEVENSEG_TEXTNC);
|
||||
}
|
||||
ResponseCmndChar(XdrvMailbox.data);
|
||||
}
|
||||
|
||||
void CmndDisplaySevensegTextNC(void) {
|
||||
if (!renderer) {
|
||||
XdspCall(FUNC_DISPLAY_SEVENSEG_TEXTNC);
|
||||
}
|
||||
ResponseCmndChar(XdrvMailbox.data);
|
||||
}
|
||||
|
||||
void CmndDisplayScrollDelay(void) {
|
||||
if (!renderer) {
|
||||
XdspCall(FUNC_DISPLAY_SCROLLDELAY);
|
||||
}
|
||||
ResponseCmndNumber(XdrvMailbox.payload);
|
||||
}
|
||||
|
||||
void CmndDisplayClock(void) {
|
||||
if (!renderer) {
|
||||
XdspCall(FUNC_DISPLAY_CLOCK);
|
||||
}
|
||||
ResponseCmndNumber(XdrvMailbox.payload);
|
||||
}
|
||||
|
||||
void CmndDisplayScrollText(void) {
|
||||
bool result = false;
|
||||
if (!renderer) {
|
||||
result = XdspCall(FUNC_DISPLAY_SCROLLTEXT);
|
||||
}
|
||||
if(result) ResponseCmndChar(XdrvMailbox.data);
|
||||
}
|
||||
|
||||
/*********************************************************************************************\
|
||||
@ -2177,46 +2182,9 @@ void DrawAClock(uint16_t rad) {
|
||||
* Graphics
|
||||
\*********************************************************************************************/
|
||||
|
||||
|
||||
#ifdef USE_GRAPH
|
||||
|
||||
typedef union {
|
||||
uint8_t data;
|
||||
struct {
|
||||
uint8_t overlay : 1;
|
||||
uint8_t draw : 1;
|
||||
uint8_t nu3 : 1;
|
||||
uint8_t nu4 : 1;
|
||||
uint8_t nu5 : 1;
|
||||
uint8_t nu6 : 1;
|
||||
uint8_t nu7 : 1;
|
||||
uint8_t nu8 : 1;
|
||||
};
|
||||
} GFLAGS;
|
||||
|
||||
struct GRAPH {
|
||||
uint16_t xp;
|
||||
uint16_t yp;
|
||||
uint16_t xs;
|
||||
uint16_t ys;
|
||||
float ymin;
|
||||
float ymax;
|
||||
float range;
|
||||
uint32_t x_time; // time per x slice in milliseconds
|
||||
uint32_t last_ms;
|
||||
uint32_t last_ms_redrawn;
|
||||
int16_t decimation; // decimation or graph duration in minutes
|
||||
uint16_t dcnt;
|
||||
uint32_t summ;
|
||||
uint16_t xcnt;
|
||||
uint8_t *values;
|
||||
uint8_t xticks;
|
||||
uint8_t yticks;
|
||||
uint8_t last_val;
|
||||
uint8_t color_index;
|
||||
GFLAGS flags;
|
||||
};
|
||||
|
||||
struct GRAPH *graph[NUM_GRAPHS];
|
||||
|
||||
#define TICKLEN 4
|
||||
void ClrGraph(uint16_t num) {
|
||||
|
@ -411,9 +411,10 @@ String GetHueDeviceId(uint16_t id)
|
||||
{
|
||||
String deviceid = WiFi.macAddress();
|
||||
deviceid += F(":00:11-");
|
||||
deviceid += String(id);
|
||||
if(id<0x10) deviceid += F("0");
|
||||
deviceid += String(id,HEX);
|
||||
deviceid.toLowerCase();
|
||||
return deviceid; // 5c:cf:7f:13:9f:3d:00:11-1
|
||||
return deviceid; // 5c:cf:7f:13:9f:3d:00:11-01
|
||||
}
|
||||
|
||||
String GetHueUserId(void)
|
||||
|
62
tasmota/xdrv_52_0_berry_struct.ino
Normal file
62
tasmota/xdrv_52_0_berry_struct.ino
Normal file
@ -0,0 +1,62 @@
|
||||
/*
|
||||
xdrv_52_0_berry_struct.ino - Berry scripting language, native fucnctions
|
||||
|
||||
Copyright (C) 2021 Stephan Hadinger, Berry language by Guan Wenliang https://github.com/Skiars/berry
|
||||
|
||||
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_BERRY
|
||||
|
||||
#include <berry.h>
|
||||
|
||||
typedef LList_elt<char[0]> log_elt; // store the string after the header to avoid double allocation if we had used char*
|
||||
|
||||
class BerryLog {
|
||||
public:
|
||||
// typedef LList_elt<char[0]> log_elt; // store the string after the header to avoid double allocation if we had used char*
|
||||
inline static size_t size(size_t chars) { return sizeof(log_elt) + chars; }
|
||||
inline bool isEmpty(void) const { return log.isEmpty(); }
|
||||
log_elt * addString(const char * s, const char * prefix = nullptr, const char * suffix = nullptr) {
|
||||
if (suffix == nullptr) { suffix = ""; }
|
||||
if (prefix == nullptr) { prefix = ""; }
|
||||
if (s == nullptr) { s = ""; }
|
||||
size_t s_len = strlen_P(s) + strlen_P(prefix) + strlen_P(suffix);
|
||||
if (0 == s_len) { return nullptr; } // do nothing
|
||||
log_elt * elt = (log_elt*) ::operator new(sizeof(log_elt) + s_len + 1); // use low-level new to specify the bytes size
|
||||
snprintf_P((char*) &elt->val(), s_len+1, PSTR("%s%s%s"), prefix, s, suffix);
|
||||
log.addToLast(elt);
|
||||
return elt;
|
||||
}
|
||||
void reset(void) {
|
||||
log.reset();
|
||||
}
|
||||
LList<char[0]> log;
|
||||
};
|
||||
|
||||
class BerrySupport {
|
||||
public:
|
||||
bvm *vm = nullptr; // berry vm
|
||||
bool rules_busy = false; // are we already processing rules, avoid infinite loop
|
||||
bool autoexec_done = false; // do we still need to load 'autoexec.be'
|
||||
bool repl_active = false; // is REPL running (activates log recording)
|
||||
// output log is stored as a LinkedList of buffers
|
||||
// and active only when a REPL command is running
|
||||
BerryLog log;
|
||||
};
|
||||
BerrySupport berry;
|
||||
|
||||
|
||||
#endif // USE_BERRY
|
@ -23,6 +23,8 @@
|
||||
#include <berry.h>
|
||||
#include <Wire.h>
|
||||
|
||||
const uint32_t BERRY_MAX_LOGS = 16; // max number of print output recorded when outside of REPL, used to avoid infinite grow of logs
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Native functions mapped to Berry functions
|
||||
*
|
||||
@ -30,18 +32,18 @@
|
||||
*
|
||||
* import tasmota
|
||||
*
|
||||
* tasmota.getfreeheap() -> int
|
||||
* tasmota.get_free_heap() -> int
|
||||
* tasmota.publish(topic:string, payload:string[, retain:bool]) -> nil
|
||||
* tasmota.cmd(command:string) -> string
|
||||
* tasmota.getoption(index:int) -> int
|
||||
* tasmota.get_option(index:int) -> int
|
||||
* tasmota.millis([delay:int]) -> int
|
||||
* tasmota.timereached(timer:int) -> bool
|
||||
* tasmota.time_reached(timer:int) -> bool
|
||||
* tasmota.yield() -> nil
|
||||
*
|
||||
* tasmota.getlight([index:int = 0]) -> map
|
||||
* tasmota.getpower([index:int = 0]) -> bool
|
||||
* tasmota.setpower(idx:int, power:bool) -> bool or nil
|
||||
* tasmota.setlight(idx:int, values:map) -> map
|
||||
* tasmota.get_light([index:int = 0]) -> map
|
||||
* tasmota.get_power([index:int = 0]) -> bool
|
||||
* tasmota.set_power(idx:int, power:bool) -> bool or nil
|
||||
* tasmota.set_light(idx:int, values:map) -> map
|
||||
*
|
||||
\*********************************************************************************************/
|
||||
extern "C" {
|
||||
@ -97,7 +99,7 @@ extern "C" {
|
||||
be_raise(vm, kTypeError, nullptr);
|
||||
}
|
||||
|
||||
// Berry: tasmota.getoption(index:int) -> int
|
||||
// Berry: tasmota.get_option(index:int) -> int
|
||||
//
|
||||
int32_t l_getoption(struct bvm *vm);
|
||||
int32_t l_getoption(struct bvm *vm) {
|
||||
@ -110,7 +112,7 @@ extern "C" {
|
||||
be_raise(vm, kTypeError, nullptr);
|
||||
}
|
||||
|
||||
// Berry: tasmota.timereached(timer:int) -> bool
|
||||
// Berry: tasmota.time_reached(timer:int) -> bool
|
||||
//
|
||||
int32_t l_timereached(struct bvm *vm);
|
||||
int32_t l_timereached(struct bvm *vm) {
|
||||
@ -145,7 +147,7 @@ extern "C" {
|
||||
be_return_nil(vm);
|
||||
}
|
||||
|
||||
// Berry: tasmota.scaleuint(int * 5) -> int
|
||||
// Berry: tasmota.scale_uint(int * 5) -> int
|
||||
//
|
||||
int32_t l_scaleuint(struct bvm *vm);
|
||||
int32_t l_scaleuint(struct bvm *vm) {
|
||||
@ -315,7 +317,7 @@ extern "C" {
|
||||
int32_t top = be_top(vm); // Get the number of arguments
|
||||
if (top == 1 || (top == 2 && be_isint(vm, 2))) {
|
||||
int32_t light_num = 0;
|
||||
if (top > 0) {
|
||||
if (top > 1) {
|
||||
light_num = be_toint(vm, 2);
|
||||
}
|
||||
push_getlight(vm, light_num);
|
||||
@ -470,6 +472,24 @@ extern "C" {
|
||||
be_raise(vm, kTypeError, nullptr);
|
||||
}
|
||||
|
||||
#ifdef USE_I2C
|
||||
// I2C specific
|
||||
// Berry: `i2c_enabled(index:int) -> bool` is I2C device enabled
|
||||
int32_t l_i2cenabled(struct bvm *vm);
|
||||
int32_t l_i2cenabled(struct bvm *vm) {
|
||||
int32_t top = be_top(vm); // Get the number of arguments
|
||||
if (top == 2 && be_isint(vm, 2)) {
|
||||
int32_t index = be_toint(vm, 2);
|
||||
bool enabled = I2cEnabled(index);
|
||||
be_pushbool(vm, enabled);
|
||||
be_return(vm); // Return
|
||||
}
|
||||
be_raise(vm, kTypeError, nullptr);
|
||||
}
|
||||
#else // USE_I2C
|
||||
int32_t l_i2cenabled(struct bvm *vm) __attribute__ ((weak, alias ("b_wire_i2cmissing")));
|
||||
#endif // USE_I2C
|
||||
|
||||
}
|
||||
|
||||
/*********************************************************************************************\
|
||||
@ -522,6 +542,13 @@ extern "C" {
|
||||
// called as a replacement to Berry `print()`
|
||||
void berry_log(const char * berry_buf);
|
||||
void berry_log(const char * berry_buf) {
|
||||
if (berry.repl_active) {
|
||||
if (berry.log.log.length() >= BERRY_MAX_LOGS) {
|
||||
berry.log.log.remove(berry.log.log.head());
|
||||
}
|
||||
}
|
||||
// AddLog(LOG_LEVEL_INFO, PSTR("[Add to log] %s"), berry_buf);
|
||||
berry.log.addString(berry_buf, nullptr, "\n");
|
||||
AddLog(LOG_LEVEL_INFO, PSTR("%s"), berry_buf);
|
||||
}
|
||||
|
||||
|
@ -48,7 +48,7 @@ int32_t getBus(bvm *vm) {
|
||||
*
|
||||
* import wire
|
||||
*
|
||||
* wire.getfreeheap() -> int
|
||||
* wire.get_free_heap() -> int
|
||||
*
|
||||
\*********************************************************************************************/
|
||||
extern "C" {
|
||||
@ -135,14 +135,18 @@ extern "C" {
|
||||
int32_t b_wire_write(struct bvm *vm);
|
||||
int32_t b_wire_write(struct bvm *vm) {
|
||||
int32_t top = be_top(vm); // Get the number of arguments
|
||||
const void * buf;
|
||||
size_t len;
|
||||
TwoWire & myWire = getWire(vm);
|
||||
if (top == 2 && (be_isint(vm, 2) || be_isstring(vm, 2))) {
|
||||
if (top == 2 && (be_isint(vm, 2) || be_isstring(vm, 2) || be_isinstance(vm, 2))) {
|
||||
if (be_isint(vm, 2)) {
|
||||
int32_t value = be_toint(vm, 2);
|
||||
myWire.write(value);
|
||||
} else if (be_isstring(vm, 2)) {
|
||||
const char * s = be_tostring(vm, 1);
|
||||
myWire.write(s);
|
||||
} else if ((buf = be_tobytes(vm, 2, &len)) != nullptr) {
|
||||
myWire.write((uint8_t*) buf, len);
|
||||
} else {
|
||||
be_return_nil(vm);
|
||||
}
|
||||
@ -211,7 +215,7 @@ extern "C" {
|
||||
uint8_t addr = be_toint(vm, 2);
|
||||
uint8_t reg = be_toint(vm, 3);
|
||||
uint8_t size = be_toint(vm, 4);
|
||||
bool ok = I2cValidRead(addr, reg, size); // TODO
|
||||
bool ok = I2cValidRead(addr, reg, size, bus); // TODO
|
||||
if (ok) {
|
||||
be_pushint(vm, i2c_buffer);
|
||||
} else {
|
||||
@ -221,6 +225,22 @@ extern "C" {
|
||||
}
|
||||
be_raise(vm, kTypeError, nullptr);
|
||||
}
|
||||
|
||||
// Berry: `find(address:int) -> bool` true if device responds
|
||||
int32_t b_wire_detect(struct bvm *vm);
|
||||
int32_t b_wire_detect(struct bvm *vm) {
|
||||
int32_t top = be_top(vm); // Get the number of arguments
|
||||
TwoWire & myWire = getWire(vm);
|
||||
if (top == 2 && be_isint(vm, 2)) {
|
||||
uint8_t addr = be_toint(vm, 2);
|
||||
// check the presence of the device
|
||||
myWire.beginTransmission((uint8_t)addr);
|
||||
bool found = (0 == myWire.endTransmission());
|
||||
be_pushbool(vm, found);
|
||||
be_return(vm); // Return
|
||||
}
|
||||
be_raise(vm, kTypeError, nullptr);
|
||||
}
|
||||
#else // USE_I2C
|
||||
//
|
||||
int32_t b_wire_i2cmissing(struct bvm *vm);
|
||||
@ -239,6 +259,9 @@ extern "C" {
|
||||
int32_t b_wire_scan(struct bvm *vm) __attribute__ ((weak, alias ("b_wire_i2cmissing")));
|
||||
int32_t b_wire_validwrite(struct bvm *vm) __attribute__ ((weak, alias ("b_wire_i2cmissing")));
|
||||
int32_t b_wire_validread(struct bvm *vm) __attribute__ ((weak, alias ("b_wire_i2cmissing")));
|
||||
int32_t b_wire_readbytes(struct bvm *vm) __attribute__ ((weak, alias ("b_wire_i2cmissing")));
|
||||
int32_t b_wire_writebytes(struct bvm *vm) __attribute__ ((weak, alias ("b_wire_i2cmissing")));
|
||||
int32_t b_wire_detect(struct bvm *vm) __attribute__ ((weak, alias ("b_wire_i2cmissing")));
|
||||
#endif // USE_I2C
|
||||
}
|
||||
|
||||
|
@ -55,14 +55,11 @@ const char berry_prog[] =
|
||||
"/f1,f2-> real(f1) < real(f2),"
|
||||
"] "
|
||||
"self._operators = \"=<>!|\" "
|
||||
"self._rules = {} "
|
||||
"self._timers = [] "
|
||||
"self._cmd = {} "
|
||||
"end "
|
||||
// add `charsinstring(s:string,c:string) -> int``
|
||||
// add `chars_in_string(s:string,c:string) -> int``
|
||||
// looks for any char in c, and return the position of the first chat
|
||||
// or -1 if not found
|
||||
"def charsinstring(s,c) "
|
||||
"def chars_in_string(s,c) "
|
||||
"for i:0..size(s)-1 "
|
||||
"for j:0..size(c)-1 "
|
||||
"if s[i] == c[j] return i end "
|
||||
@ -72,7 +69,7 @@ const char berry_prog[] =
|
||||
"end "
|
||||
|
||||
// find a key in map, case insensitive, return actual key or nil if not found
|
||||
"def findkeyi(m,keyi) "
|
||||
"def find_key_i(m,keyi) "
|
||||
"import string "
|
||||
"var keyu = string.toupper(keyi) "
|
||||
"if classof(m) == map "
|
||||
@ -84,14 +81,11 @@ const char berry_prog[] =
|
||||
"end "
|
||||
"end "
|
||||
|
||||
// Rules
|
||||
"def addrule(pat,f) self._rules[pat] = f end "
|
||||
|
||||
// # split the item when there is an operator, returns a list of (left,op,right)
|
||||
// # ex: "Dimmer>50" -> ["Dimmer",tasmota_gt,"50"]
|
||||
"def find_op(item) "
|
||||
"import string "
|
||||
"var pos = self.charsinstring(item, self._operators) "
|
||||
"var pos = self.chars_in_string(item, self._operators) "
|
||||
"if pos>=0 "
|
||||
"var op_split = string.split(item,pos) "
|
||||
// #print(op_split)
|
||||
@ -109,6 +103,14 @@ const char berry_prog[] =
|
||||
"end "
|
||||
"return [item, nil, nil] "
|
||||
"end "
|
||||
|
||||
// Rules
|
||||
"def add_rule(pat,f) "
|
||||
"if !self._rules "
|
||||
"self._rules={} "
|
||||
"end "
|
||||
"self._rules[pat] = f "
|
||||
"end "
|
||||
|
||||
// Rules trigger if match. return true if match, false if not
|
||||
"def try_rule(ev, rule, f) "
|
||||
@ -117,7 +119,7 @@ const char berry_prog[] =
|
||||
"var e=ev "
|
||||
"var rl=string.split(rl_list[0],'#') "
|
||||
"for it:rl "
|
||||
"found=self.findkeyi(e,it) "
|
||||
"found=self.find_key_i(e,it) "
|
||||
"if found == nil "
|
||||
"return false "
|
||||
"end "
|
||||
@ -138,55 +140,69 @@ const char berry_prog[] =
|
||||
// Run rules, i.e. check each individual rule
|
||||
// Returns true if at least one rule matched, false if none
|
||||
"def exec_rules(ev_json) "
|
||||
"import json "
|
||||
"var ev = json.load(ev_json) "
|
||||
"var ret = false "
|
||||
"if ev == nil "
|
||||
"print('BRY: ERROR, bad json: '+ev_json, 3) "
|
||||
"else "
|
||||
"for r: self._rules.keys() "
|
||||
"ret = self.try_rule(ev,r,self._rules[r]) || ret "
|
||||
"if self._rules "
|
||||
"import json "
|
||||
"var ev = json.load(ev_json) "
|
||||
"var ret = false "
|
||||
"if ev == nil "
|
||||
"print('BRY: ERROR, bad json: '+ev_json, 3) "
|
||||
"else "
|
||||
"for r: self._rules.keys() "
|
||||
"ret = self.try_rule(ev,r,self._rules[r]) || ret "
|
||||
"end "
|
||||
"end "
|
||||
"return ret "
|
||||
"end "
|
||||
"return ret "
|
||||
"return false "
|
||||
"end "
|
||||
|
||||
"def settimer(delay,f) self._timers.push([self.millis(delay),f]) end "
|
||||
"def set_timer(delay,f) "
|
||||
"if !self._timers self._timers=[] end "
|
||||
"self._timers.push([self.millis(delay),f]) "
|
||||
"end "
|
||||
|
||||
// run every 50ms tick
|
||||
"def run_deferred() "
|
||||
"var i=0 "
|
||||
"while i<self._timers.size() "
|
||||
"if self.timereached(self._timers[i][0]) "
|
||||
"f=self._timers[i][1] "
|
||||
"self._timers.remove(i) "
|
||||
"f() "
|
||||
"else "
|
||||
"i=i+1 "
|
||||
"if self._timers "
|
||||
"var i=0 "
|
||||
"while i<self._timers.size() "
|
||||
"if self.time_reached(self._timers[i][0]) "
|
||||
"f=self._timers[i][1] "
|
||||
"self._timers.remove(i) "
|
||||
"f() "
|
||||
"else "
|
||||
"i=i+1 "
|
||||
"end "
|
||||
"end "
|
||||
"end "
|
||||
"end "
|
||||
|
||||
// Delay function, internally calls yield() every 10ms to avoid WDT
|
||||
"def delay(ms) "
|
||||
"var tend = self.millis(ms) "
|
||||
"while !self.timereached(tend) "
|
||||
"self.yield() "
|
||||
"end "
|
||||
"end "
|
||||
// // Delay function, internally calls yield() every 10ms to avoid WDT
|
||||
// "def delay(ms) "
|
||||
// "var tend = self.millis(ms) "
|
||||
// "while !self.time_reached(tend) "
|
||||
// "self.yield() "
|
||||
// "end "
|
||||
// "end "
|
||||
|
||||
// Add command to list
|
||||
"def addcommand(c,f) "
|
||||
"def add_cmd(c,f) "
|
||||
"if !self._cmd "
|
||||
"self._cmd={} "
|
||||
"end "
|
||||
"self._cmd[c]=f "
|
||||
"end "
|
||||
|
||||
"def exec_cmd(cmd, idx, payload) "
|
||||
"import json "
|
||||
"var payload_json = json.load(payload) "
|
||||
"var cmd_found = self.findkeyi(self._cmd, cmd) "
|
||||
"if cmd_found != nil "
|
||||
"self.resolvecmnd(cmd_found) " // set the command name in XdrvMailbox.command
|
||||
"self._cmd[cmd_found](cmd_found, idx, payload, payload_json) "
|
||||
"return true "
|
||||
"if self._cmd "
|
||||
"import json "
|
||||
"var payload_json = json.load(payload) "
|
||||
"var cmd_found = self.find_key_i(self._cmd, cmd) "
|
||||
"if cmd_found != nil "
|
||||
"self.resolvecmnd(cmd_found) " // set the command name in XdrvMailbox.command
|
||||
"self._cmd[cmd_found](cmd_found, idx, payload, payload_json) "
|
||||
"return true "
|
||||
"end "
|
||||
"end "
|
||||
"return false "
|
||||
"end "
|
||||
@ -198,18 +214,86 @@ const char berry_prog[] =
|
||||
"return gc.allocated() "
|
||||
"end "
|
||||
|
||||
//
|
||||
// Event from Tasmota is:
|
||||
// 1. event:string -- type of event (cmd, rule, ...)
|
||||
// 2. cmd:string -- name of the command to process
|
||||
// 3. index:int -- index number
|
||||
// 4. payload:string -- payload as text, analyzed as json
|
||||
//
|
||||
"def event(type, cmd, idx, payload) "
|
||||
"if type=='cmd' return self.exec_cmd(cmd, idx, payload) "
|
||||
"elif type=='rule' return self.exec_rules(payload) "
|
||||
"elif type=='mqtt_data' return nil " // not yet implemented
|
||||
"elif type=='gc' return self.gc() "
|
||||
"elif type=='every_50ms' return self.run_deferred() "
|
||||
"elif self._drivers "
|
||||
"for d:self._drivers "
|
||||
"try "
|
||||
"if d.dispatch && d.dispatch(type, cmd, idx, payload) nil " // nil for `nop`
|
||||
"elif type=='every_second' && d.every_second return d.every_second() "
|
||||
"elif type=='every_100ms' && d.every_100ms return d.every_100ms() "
|
||||
"end "
|
||||
"except .. as e,m "
|
||||
"import string "
|
||||
"log(string.format('BRY: exception %s - %m',3)) "
|
||||
"end "
|
||||
"end "
|
||||
"end "
|
||||
"end "
|
||||
//
|
||||
// add driver to the queue of event dispatching
|
||||
//
|
||||
"def add_driver(d) "
|
||||
"if self._drivers "
|
||||
"self._drivers.push(d) "
|
||||
"else "
|
||||
"self._drivers = [d]"
|
||||
"end "
|
||||
"end "
|
||||
|
||||
"end "
|
||||
|
||||
// Instantiate tasmota object
|
||||
"tasmota = Tasmota() "
|
||||
"wire = Wire(0) "
|
||||
"wire1 = Wire(1) "
|
||||
|
||||
// Not sure how to run call methods from C
|
||||
"def _exec_rules(e) return tasmota.exec_rules(e) end "
|
||||
"def _run_deferred() return tasmota.run_deferred() end "
|
||||
"def _exec_cmd(cmd, idx, payload) return tasmota.exec_cmd(cmd, idx, payload) end "
|
||||
"def _gc() return tasmota.gc() end "
|
||||
// Wire class
|
||||
"class Wire : Wire_ntv "
|
||||
// read bytes as `bytes()` object
|
||||
"def read_bytes(addr,reg,size) "
|
||||
"self._begin_transmission(addr) "
|
||||
"self._write(reg) "
|
||||
"self._end_transmission(false) "
|
||||
"self._request_from(addr,size) "
|
||||
"var ret=bytes(size) "
|
||||
"while (self._available()) "
|
||||
"ret..self._read() "
|
||||
"end "
|
||||
"return ret "
|
||||
"end "
|
||||
// write bytes from `bytes` object
|
||||
"def write_bytes(addr,reg,b) "
|
||||
"self._begin_transmission(addr) "
|
||||
"self._write(reg) "
|
||||
"self._write(b) "
|
||||
"self._end_transmission() "
|
||||
"end "
|
||||
"end "
|
||||
|
||||
"wire = Wire(0) "
|
||||
"wire1 = wire "
|
||||
"wire2 = Wire(1) "
|
||||
|
||||
//
|
||||
// Base class for Tasmota Driver
|
||||
//
|
||||
"class Driver "
|
||||
// functions are needs to be set to trigger an event
|
||||
"var dispatch " // general dispatcher, returns true if serviced
|
||||
"var every_second " // called every_second
|
||||
"var every_100ms " // called every 100ms
|
||||
// ...
|
||||
"end "
|
||||
|
||||
// simple wrapper to load a file
|
||||
// prefixes '/' if needed, and simpler to use than `compile()`
|
||||
|
@ -24,6 +24,8 @@
|
||||
|
||||
#include <berry.h>
|
||||
|
||||
#define BERRY_CONSOLE_CMD_DELIMITER "\x01"
|
||||
|
||||
const char kBrCommands[] PROGMEM = D_PRFX_BR "|" // prefix
|
||||
D_CMND_BR_RUN "|" D_CMND_BR_RESET
|
||||
;
|
||||
@ -32,14 +34,6 @@ void (* const BerryCommand[])(void) PROGMEM = {
|
||||
CmndBrRun, CmndBrReset,
|
||||
};
|
||||
|
||||
class BerrySupport {
|
||||
public:
|
||||
bvm *vm = nullptr; // berry vm
|
||||
bool rules_busy = false; // are we already processing rules, avoid infinite loop
|
||||
bool autoexec_done = false; // do we still need to load 'autoexec.be'
|
||||
};
|
||||
BerrySupport berry;
|
||||
|
||||
//
|
||||
// Sanity Check for be_top()
|
||||
//
|
||||
@ -53,6 +47,32 @@ void checkBeTop(void) {
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Memory handler
|
||||
* Use PSRAM if available
|
||||
\*********************************************************************************************/
|
||||
extern "C" {
|
||||
void *berry_malloc(uint32_t size);
|
||||
void *berry_realloc(void *ptr, size_t size);
|
||||
#ifdef USE_BERRY_PSRAM
|
||||
void *berry_malloc(uint32_t size) {
|
||||
return special_malloc(size);
|
||||
}
|
||||
void *berry_realloc(void *ptr, size_t size) {
|
||||
return special_realloc(ptr, size);
|
||||
}
|
||||
#else
|
||||
void *berry_malloc(uint32_t size) {
|
||||
return malloc(size);
|
||||
}
|
||||
void *berry_realloc(void *ptr, size_t size) {
|
||||
return realloc(ptr, size);
|
||||
}
|
||||
#endif // USE_BERRY_PSRAM
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Handlers for Berry calls and async
|
||||
*
|
||||
@ -64,79 +84,13 @@ bool callBerryRule(void) {
|
||||
berry.rules_busy = true;
|
||||
char * json_event = TasmotaGlobal.mqtt_data;
|
||||
bool serviced = false;
|
||||
|
||||
checkBeTop();
|
||||
be_getglobal(berry.vm, "_exec_rules");
|
||||
if (!be_isnil(berry.vm, -1)) {
|
||||
|
||||
// {
|
||||
// String event_saved = TasmotaGlobal.mqtt_data;
|
||||
// // json_event = {"INA219":{"Voltage":4.494,"Current":0.020,"Power":0.089}}
|
||||
// // json_event = {"System":{"Boot":1}}
|
||||
// // json_event = {"SerialReceived":"on"} - invalid but will be expanded to {"SerialReceived":{"Data":"on"}}
|
||||
// char *p = strchr(json_event, ':');
|
||||
// if ((p != NULL) && !(strchr(++p, ':'))) { // Find second colon
|
||||
// event_saved.replace(F(":"), F(":{\"Data\":"));
|
||||
// event_saved += F("}");
|
||||
// // event_saved = {"SerialReceived":{"Data":"on"}}
|
||||
// }
|
||||
// be_pushstring(berry.vm, event_saved.c_str());
|
||||
// }
|
||||
be_pushstring(berry.vm, TasmotaGlobal.mqtt_data);
|
||||
int ret = be_pcall(berry.vm, 1);
|
||||
serviced = be_tobool(berry.vm, 1);
|
||||
AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_BERRY "Event (%s) serviced=%d"), TasmotaGlobal.mqtt_data, serviced);
|
||||
be_pop(berry.vm, 2); // remove function object
|
||||
} else {
|
||||
be_pop(berry.vm, 1); // remove nil object
|
||||
}
|
||||
checkBeTop();
|
||||
serviced = callBerryEventDispatcher(PSTR("rule"), nullptr, 0, TasmotaGlobal.mqtt_data);
|
||||
berry.rules_busy = false;
|
||||
|
||||
return serviced; // TODO event not handled
|
||||
}
|
||||
|
||||
bool callBerryCommand(void) {
|
||||
bool serviced = false;
|
||||
|
||||
checkBeTop();
|
||||
be_getglobal(berry.vm, "_exec_cmd");
|
||||
if (!be_isnil(berry.vm, -1)) {
|
||||
be_pushstring(berry.vm, XdrvMailbox.topic);
|
||||
be_pushint(berry.vm, XdrvMailbox.index);
|
||||
be_pushstring(berry.vm, XdrvMailbox.data);
|
||||
int ret = be_pcall(berry.vm, 3);
|
||||
// AddLog(LOG_LEVEL_INFO, "callBerryCommand: top=%d", be_top(berry.vm));
|
||||
// AddLog(LOG_LEVEL_INFO, "callBerryCommand: type(1)=%s", be_typename(berry.vm, 1));
|
||||
// AddLog(LOG_LEVEL_INFO, "callBerryCommand: type(2)=%s", be_typename(berry.vm, 2));
|
||||
// AddLog(LOG_LEVEL_INFO, "callBerryCommand: type(3)=%s", be_typename(berry.vm, 3));
|
||||
// AddLog(LOG_LEVEL_INFO, "callBerryCommand: type(4)=%s", be_typename(berry.vm, 4));
|
||||
// AddLog(LOG_LEVEL_INFO, "callBerryCommand: type(5)=%s", be_typename(berry.vm, 5));
|
||||
serviced = be_tobool(berry.vm, 1); // return value is in slot 1
|
||||
// AddLog(LOG_LEVEL_INFO, "callBerryCommand: serviced=%d", serviced);
|
||||
be_pop(berry.vm, 4); // remove function object
|
||||
} else {
|
||||
be_pop(berry.vm, 1); // remove nil object
|
||||
}
|
||||
checkBeTop();
|
||||
|
||||
return serviced; // TODO event not handled
|
||||
}
|
||||
|
||||
size_t callBerryGC(void) {
|
||||
size_t ram_used = 0;
|
||||
checkBeTop();
|
||||
be_getglobal(berry.vm, "_gc");
|
||||
if (!be_isnil(berry.vm, -1)) {
|
||||
int ret = be_pcall(berry.vm, 0);
|
||||
ram_used = be_toint(berry.vm, 1);
|
||||
be_pop(berry.vm, 1); // remove function object
|
||||
} else {
|
||||
be_pop(berry.vm, 1); // remove nil object
|
||||
}
|
||||
checkBeTop();
|
||||
|
||||
return ram_used;
|
||||
return callBerryEventDispatcher(PSTR("gc"), nullptr, 0, nullptr);
|
||||
}
|
||||
|
||||
// void callBerryMqttData(void) {
|
||||
@ -161,16 +115,79 @@ size_t callBerryGC(void) {
|
||||
// checkBeTop();
|
||||
// }
|
||||
|
||||
// call a function (if exists) of type void -> void
|
||||
void callBerryFunctionVoid(const char * fname) {
|
||||
if (nullptr == berry.vm) { return; }
|
||||
checkBeTop();
|
||||
be_getglobal(berry.vm, fname);
|
||||
/*
|
||||
// Call a method of a global object, with n args
|
||||
// Before: stack must containt n args
|
||||
// After: stack contains return value or nil if something wrong (args removes)
|
||||
// returns true is successful, false if object or method not found
|
||||
bool callMethodObjectWithArgs(const char * objname, const char * method, size_t argc) {
|
||||
if (nullptr == berry.vm) { return false; }
|
||||
int32_t top = be_top(berry.vm);
|
||||
// stacks contains n x arg
|
||||
be_getglobal(berry.vm, objname);
|
||||
// stacks contains n x arg + object
|
||||
if (!be_isnil(berry.vm, -1)) {
|
||||
be_pcall(berry.vm, 0);
|
||||
be_getmethod(berry.vm, -1, method);
|
||||
// stacks contains n x arg + object + method
|
||||
if (!be_isnil(berry.vm, -1)) {
|
||||
// reshuffle the entire stack since we want: method + object + n x arg
|
||||
be_pushvalue(berry.vm, -1); // add instance as first arg
|
||||
// stacks contains n x arg + object + method + method
|
||||
be_pushvalue(berry.vm, -3); // add instance as first arg
|
||||
// stacks contains n x arg + object + method + method + object
|
||||
// now move args 2 slots up to make room for method and object
|
||||
for (uint32_t i = 1; i <= argc; i++) {
|
||||
be_moveto(berry.vm, -4 - i, -2 - i);
|
||||
}
|
||||
// stacks contains free + free + n x arg + method + object
|
||||
be_moveto(berry.vm, -2, -4 - argc);
|
||||
be_moveto(berry.vm, -1, -3 - argc);
|
||||
// stacks contains method + object + n x arg + method + object
|
||||
be_pop(berry.vm, 2);
|
||||
// stacks contains method + object + n x arg
|
||||
be_pcall(berry.vm, argc + 1);
|
||||
// stacks contains return_val + object + n x arg
|
||||
be_pop(berry.vm, argc + 1);
|
||||
// stacks contains return_val
|
||||
return true;
|
||||
}
|
||||
be_pop(berry.vm, 1); // remove method
|
||||
// stacks contains n x arg + object
|
||||
}
|
||||
be_pop(berry.vm, 1); // remove function or nil object
|
||||
// stacks contains n x arg + object
|
||||
be_pop(berry.vm, argc + 1); // clear stack
|
||||
be_pushnil(berry.vm); // put nil object
|
||||
return false;
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
// call the event dispatcher from Tasmota object
|
||||
int32_t callBerryEventDispatcher(const char *type, const char *cmd, int32_t idx, const char *payload) {
|
||||
int32_t ret = 0;
|
||||
|
||||
if (nullptr == berry.vm) { return ret; }
|
||||
checkBeTop();
|
||||
be_getglobal(berry.vm, PSTR("tasmota"));
|
||||
if (!be_isnil(berry.vm, -1)) {
|
||||
be_getmethod(berry.vm, -1, PSTR("event"));
|
||||
if (!be_isnil(berry.vm, -1)) {
|
||||
be_pushvalue(berry.vm, -2); // add instance as first arg
|
||||
be_pushstring(berry.vm, type != nullptr ? type : "");
|
||||
be_pushstring(berry.vm, cmd != nullptr ? cmd : "");
|
||||
be_pushint(berry.vm, idx);
|
||||
be_pushstring(berry.vm, payload != nullptr ? payload : "{}"); // empty json
|
||||
be_pcall(berry.vm, 5); // 5 arguments
|
||||
be_pop(berry.vm, 5);
|
||||
if (be_isint(berry.vm, -1)) {
|
||||
ret = be_toint(berry.vm, -1);
|
||||
}
|
||||
}
|
||||
be_pop(berry.vm, 1); // remove method
|
||||
}
|
||||
be_pop(berry.vm, 1); // remove instance object
|
||||
checkBeTop();
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*********************************************************************************************\
|
||||
@ -349,6 +366,313 @@ void CmndBrReset(void) {
|
||||
BrReset();
|
||||
}
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Berry console
|
||||
\*********************************************************************************************/
|
||||
#ifdef USE_WEBSERVER
|
||||
|
||||
void BrREPLRun(char * cmd) {
|
||||
if (berry.vm == nullptr) { return; }
|
||||
|
||||
size_t cmd_len = strlen(cmd);
|
||||
size_t cmd2_len = cmd_len + 12;
|
||||
char * cmd2 = (char*) malloc(cmd2_len);
|
||||
do {
|
||||
int32_t ret_code;
|
||||
|
||||
snprintf_P(cmd2, cmd2_len, PSTR("return (%s)"), cmd);
|
||||
ret_code = be_loadbuffer(berry.vm, PSTR("input"), cmd2, strlen(cmd2));
|
||||
// AddLog(LOG_LEVEL_INFO, PSTR(">>>> be_loadbuffer cmd2 '%s', ret=%i"), cmd2, ret_code);
|
||||
if (be_getexcept(berry.vm, ret_code) == BE_SYNTAX_ERROR) {
|
||||
be_pop(berry.vm, 2); // remove exception values
|
||||
// if fails, try the direct command
|
||||
ret_code = be_loadbuffer(berry.vm, PSTR("input"), cmd, cmd_len);
|
||||
// AddLog(LOG_LEVEL_INFO, PSTR(">>>> be_loadbuffer cmd1 '%s', ret=%i"), cmd, ret_code);
|
||||
}
|
||||
if (0 == ret_code) { // code is ready to run
|
||||
ret_code = be_pcall(berry.vm, 0); // execute code
|
||||
// AddLog(LOG_LEVEL_INFO, PSTR(">>>> be_pcall ret=%i"), ret_code);
|
||||
if (0 == ret_code) {
|
||||
if (!be_isnil(berry.vm, 1)) {
|
||||
const char * ret_val = be_tostring(berry.vm, 1);
|
||||
berry.log.addString(ret_val, nullptr, "\n");
|
||||
// AddLog_P(LOG_LEVEL_INFO, PSTR(">>> %s"), ret_val);
|
||||
}
|
||||
be_pop(berry.vm, 1);
|
||||
}
|
||||
}
|
||||
if (BE_EXCEPTION == ret_code) {
|
||||
be_dumpstack(berry.vm);
|
||||
char exception_s[120];
|
||||
ext_snprintf_P(exception_s, sizeof(exception_s), PSTR("%s: %s"), be_tostring(berry.vm, -2), be_tostring(berry.vm, -1));
|
||||
berry.log.addString(exception_s, nullptr, "\n");
|
||||
// AddLog_P(LOG_LEVEL_INFO, PSTR(">>> %s"), exception_s);
|
||||
be_pop(berry.vm, 2);
|
||||
}
|
||||
} while(0);
|
||||
|
||||
if (cmd2 != nullptr) {
|
||||
free(cmd2);
|
||||
cmd2 = nullptr;
|
||||
}
|
||||
checkBeTop();
|
||||
}
|
||||
|
||||
const char HTTP_SCRIPT_BERRY_CONSOLE[] PROGMEM =
|
||||
"var sn=0,id=0,ft,ltm=%d;" // Scroll position, Get most of weblog initially
|
||||
// Console command history
|
||||
"var hc=[],cn=0;" // hc = History commands, cn = Number of history being shown
|
||||
|
||||
"function l(p){" // Console log and command service
|
||||
"var c,cc,o='';"
|
||||
"clearTimeout(lt);"
|
||||
"clearTimeout(ft);"
|
||||
"t=eb('t1');"
|
||||
"if(p==1){"
|
||||
"c=eb('c1');" // Console command id
|
||||
"cc=c.value.trim();"
|
||||
"if(cc){"
|
||||
"o='&c1='+encodeURIComponent(cc);"
|
||||
"hc.length>19&&hc.pop();"
|
||||
"hc.unshift(cc);"
|
||||
"cn=0;"
|
||||
"}"
|
||||
"c.value='';"
|
||||
"t.scrollTop=99999;"
|
||||
"sn=t.scrollTop;"
|
||||
"}"
|
||||
"if(t.scrollTop>=sn){" // User scrolled back so no updates
|
||||
"if(x!=null){x.abort();}" // Abort if no response within 2 seconds (happens on restart 1)
|
||||
"x=new XMLHttpRequest();"
|
||||
"x.onreadystatechange=function(){"
|
||||
"if(x.readyState==4&&x.status==200){"
|
||||
"var d,t1;"
|
||||
"d=x.responseText.split(/" BERRY_CONSOLE_CMD_DELIMITER "/);" // Field separator
|
||||
"var d1=d.shift();"
|
||||
"if(d1){"
|
||||
"t1=document.createElement('div');"
|
||||
"t1.classList.add('br1');"
|
||||
"t1.innerText=d1;"
|
||||
"t.appendChild(t1);"
|
||||
"}"
|
||||
"d1=d.shift();"
|
||||
"if(d1){"
|
||||
"t1=document.createElement('div');"
|
||||
"t1.classList.add('br2');"
|
||||
"t1.innerText=d1;"
|
||||
"t.appendChild(t1);"
|
||||
"}"
|
||||
"t.scrollTop=99999;"
|
||||
"sn=t.scrollTop;"
|
||||
"clearTimeout(ft);"
|
||||
"lt=setTimeout(l,ltm);" // webrefresh timer....
|
||||
"}"
|
||||
"};"
|
||||
"x.open('GET','bs?c2='+id+o,true);" // Related to Webserver->hasArg("c2") and WebGetArg("c2", stmp, sizeof(stmp))
|
||||
"x.send();"
|
||||
"ft=setTimeout(l,20000);" // fail timeout, triggered 20s after asking for XHR
|
||||
"}else{"
|
||||
"lt=setTimeout(l,ltm);" // webrefresh timer....
|
||||
"}"
|
||||
"c1.focus();"
|
||||
"return false;"
|
||||
"}"
|
||||
"wl(l);" // Load initial console text
|
||||
; // Add console command key eventlistener after name has been synced with id (= wl(jd))
|
||||
|
||||
const char HTTP_SCRIPT_BERRY_CONSOLE2[] PROGMEM =
|
||||
// // Console command history
|
||||
// "var hc=[],cn=0;" // hc = History commands, cn = Number of history being shown
|
||||
"var pc=0;" // pc = previous char
|
||||
"function h(){"
|
||||
// "if(!(navigator.maxTouchPoints||'ontouchstart'in document.documentElement)){eb('c1').autocomplete='off';}" // No touch so stop browser autocomplete
|
||||
"eb('c1').addEventListener('keydown',function(e){"
|
||||
"var b=eb('c1'),c=e.keyCode;" // c1 = Console command id
|
||||
"if((38==c||40==c)&&0==this.selectionStart&&0==this.selectionEnd){"
|
||||
"b.autocomplete='off';"
|
||||
"e.preventDefault();"
|
||||
"38==c?(++cn>hc.length&&(cn=hc.length),b.value=hc[cn-1]||''):" // ArrowUp
|
||||
"40==c?(0>--cn&&(cn=0),b.value=hc[cn-1]||''):" // ArrowDown
|
||||
"0;"
|
||||
"this.selectionStart=this.selectionEnd=0;"
|
||||
"}" // ArrowUp or ArrowDown must be a keyboard so stop browser autocomplete
|
||||
"if(c==13&&pc==13){"
|
||||
"e.preventDefault();" // prevent 'enter' from being inserted
|
||||
"l(1);"
|
||||
"}"
|
||||
"if(c==9){"
|
||||
"e.preventDefault();"
|
||||
"var start=this.selectionStart;"
|
||||
"var end=this.selectionEnd;"
|
||||
// set textarea value to: text before caret + tab + text after caret
|
||||
"this.value=this.value.substring(0, start)+\" \"+this.value.substring(end);"
|
||||
// put caret at right position again
|
||||
"this.selectionStart=this.selectionEnd=start + 1;"
|
||||
"}"
|
||||
"pc=c;" // record previous key
|
||||
// "13==c&&(hc.length>19&&hc.pop(),hc.unshift(b.value),cn=0)" // Enter, 19 = Max number -1 of commands in history
|
||||
"});"
|
||||
"}"
|
||||
"wl(h);"; // Add console command key eventlistener after name has been synced with id (= wl(jd))
|
||||
|
||||
const char HTTP_BERRY_STYLE_CMND[] PROGMEM =
|
||||
"<style>"
|
||||
".br1{" // berry output
|
||||
"border-left:dotted 2px #860;"
|
||||
"margin-bottom:4px;"
|
||||
"margin-top:4px;"
|
||||
"padding:1px 5px 1px 18px;"
|
||||
"}"
|
||||
".br2{" // user input
|
||||
"padding:0px 5px 0px 5px;"
|
||||
"color:#faffff;"
|
||||
"}"
|
||||
".br0{"
|
||||
// "-moz-appearance: textfield-multiline;"
|
||||
// "-webkit-appearance: textarea;"
|
||||
"font:medium -moz-fixed;"
|
||||
"font:-webkit-small-control;"
|
||||
"box-sizing:border-box;"
|
||||
"width:100%;"
|
||||
"overflow:auto;"
|
||||
"resize:vertical;"
|
||||
"font-family:monospace;"
|
||||
"overflow:auto;"
|
||||
"font-size:1em;"
|
||||
"}"
|
||||
".bro{"
|
||||
// "-moz-appearance: textfield-multiline;"
|
||||
// "-webkit-appearance: textarea;"
|
||||
"border:1px solid gray;"
|
||||
"height:250px;"
|
||||
"padding:2px;"
|
||||
"background:#222;"
|
||||
"color:#fb1;"
|
||||
"white-space:pre;"
|
||||
"padding:2px 5px 2px 5px;"
|
||||
"}"
|
||||
".bri{"
|
||||
// "-moz-appearance: textfield-multiline;"
|
||||
// "-webkit-appearance: textarea;"
|
||||
"border:1px solid gray;"
|
||||
"height:60px;"
|
||||
"padding:5px;"
|
||||
"color:#000000;background:#faffff"
|
||||
"}"
|
||||
"</style>"
|
||||
;
|
||||
|
||||
const char HTTP_BERRY_FORM_CMND[] PROGMEM =
|
||||
"<br>"
|
||||
"<div contenteditable='false' class='br0 bro' readonly id='t1' cols='340' wrap='off'>"
|
||||
"<div class='br1'>Welcome to the Berry Scripting console. "
|
||||
"Check the <a href='https://tasmota.github.io/docs/Berry-Scripting/' target='_blank'>documentation</a>."
|
||||
"</div>"
|
||||
"</div>"
|
||||
// "<textarea readonly id='t1' cols='340' wrap='off'></textarea>"
|
||||
// "<br><br>"
|
||||
"<form method='get' id='fo' onsubmit='return l(1);'>"
|
||||
"<textarea id='c1' class='br0 bri' rows='4' cols='340' wrap='soft' autofocus required></textarea>"
|
||||
// "<input id='c1' class='bri' type='text' rows='5' placeholder='" D_ENTER_COMMAND "' autofocus><br>"
|
||||
// "<input type='submit' value=\"Run code (or press 'Enter' twice)\">"
|
||||
"<button type='submit'>Run code (or press 'Enter' twice)</button>"
|
||||
"</form>";
|
||||
|
||||
const char HTTP_BTN_BERRY_CONSOLE[] PROGMEM =
|
||||
"<p><form action='bs' method='get'><button>Berry Scripting console</button></form></p>";
|
||||
|
||||
|
||||
void HandleBerryConsoleRefresh(void)
|
||||
{
|
||||
String svalue = Webserver->arg(F("c1"));
|
||||
|
||||
svalue.trim();
|
||||
if (svalue.length()) {
|
||||
berry.log.reset(); // clear all previous logs
|
||||
berry.repl_active = true; // start recording
|
||||
// AddLog_P(LOG_LEVEL_INFO, PSTR("BRY: received command %s"), svalue.c_str());
|
||||
berry.log.addString(svalue.c_str(), nullptr, BERRY_CONSOLE_CMD_DELIMITER);
|
||||
|
||||
// Call berry
|
||||
BrREPLRun((char*)svalue.c_str());
|
||||
berry.repl_active = false; // don't record further
|
||||
}
|
||||
|
||||
WSContentBegin(200, CT_PLAIN);
|
||||
|
||||
if (!berry.log.isEmpty()) {
|
||||
|
||||
WSContentFlush();
|
||||
|
||||
for (auto & l: berry.log.log) {
|
||||
_WSContentSend((char*) l);
|
||||
}
|
||||
|
||||
berry.log.reset();
|
||||
}
|
||||
WSContentEnd();
|
||||
}
|
||||
|
||||
void HandleBerryConsole(void)
|
||||
{
|
||||
if (!HttpCheckPriviledgedAccess()) { return; }
|
||||
// int i=16;
|
||||
// // AddLog(LOG_LEVEL_INFO, PSTR("Size = %d %d"), sizeof(LList_elt<char[12]>), sizeof(LList_elt<char[0]>)+12);
|
||||
// LList_elt<char[0]> * elt = (LList_elt<char[0]>*) ::operator new(sizeof(LList_elt<char[0]>) + 12);
|
||||
|
||||
if (Webserver->hasArg(F("c2"))) { // Console refresh requested
|
||||
HandleBerryConsoleRefresh();
|
||||
return;
|
||||
}
|
||||
|
||||
AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP "Berry " D_CONSOLE));
|
||||
|
||||
WSContentStart_P(PSTR("Berry " D_CONSOLE));
|
||||
WSContentSend_P(HTTP_SCRIPT_BERRY_CONSOLE, Settings.web_refresh);
|
||||
WSContentSend_P(HTTP_SCRIPT_BERRY_CONSOLE2);
|
||||
WSContentSendStyle();
|
||||
WSContentFlush();
|
||||
_WSContentSend(HTTP_BERRY_STYLE_CMND);
|
||||
_WSContentSend(HTTP_BERRY_FORM_CMND);
|
||||
WSContentSpaceButton(BUTTON_MAIN);
|
||||
WSContentStop();
|
||||
}
|
||||
|
||||
// void HandleBerryConsoleRefresh(void)
|
||||
// {
|
||||
// String svalue = Webserver->arg(F("c1"));
|
||||
// if (svalue.length() && (svalue.length() < MQTT_MAX_PACKET_SIZE)) {
|
||||
// // TODO run command and store result
|
||||
// // AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_COMMAND "%s"), svalue.c_str());
|
||||
// // ExecuteWebCommand((char*)svalue.c_str(), SRC_WEBCONSOLE);
|
||||
// }
|
||||
|
||||
// char stmp[8];
|
||||
// WebGetArg(PSTR("c2"), stmp, sizeof(stmp));
|
||||
// uint32_t index = 0; // Initial start, dump all
|
||||
// if (strlen(stmp)) { index = atoi(stmp); }
|
||||
|
||||
// WSContentBegin(200, CT_PLAIN);
|
||||
// WSContentSend_P(PSTR("%d}1%d}1"), TasmotaGlobal.log_buffer_pointer, Web.reset_web_log_flag);
|
||||
// if (!Web.reset_web_log_flag) {
|
||||
// index = 0;
|
||||
// Web.reset_web_log_flag = true;
|
||||
// }
|
||||
// bool cflg = (index);
|
||||
// char* line;
|
||||
// size_t len;
|
||||
// while (GetLog(Settings.weblog_level, &index, &line, &len)) {
|
||||
// if (len > sizeof(TasmotaGlobal.mqtt_data) -2) { len = sizeof(TasmotaGlobal.mqtt_data); }
|
||||
// char stemp[len +1];
|
||||
// strlcpy(stemp, line, len);
|
||||
// WSContentSend_P(PSTR("%s%s"), (cflg) ? PSTR("\n") : "", stemp);
|
||||
// cflg = true;
|
||||
// }
|
||||
// WSContentSend_P(PSTR("}1"));
|
||||
// WSContentEnd();
|
||||
// }
|
||||
#endif // USE_WEBSERVER
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Interface
|
||||
\*********************************************************************************************/
|
||||
@ -363,51 +687,63 @@ bool Xdrv52(uint8_t function)
|
||||
break;
|
||||
case FUNC_LOOP:
|
||||
if (!berry.autoexec_done) {
|
||||
BrAutoexec();
|
||||
BrAutoexec(); // run autoexec.be at first tick, so we know all modules are initialized
|
||||
berry.autoexec_done = true;
|
||||
}
|
||||
break;
|
||||
|
||||
// Berry wide commands and events
|
||||
case FUNC_RULES_PROCESS:
|
||||
result = callBerryRule();
|
||||
break;
|
||||
case FUNC_MQTT_DATA:
|
||||
result = callBerryEventDispatcher(PSTR("mqtt_data"), XdrvMailbox.topic, 0, XdrvMailbox.data);
|
||||
break;
|
||||
case FUNC_EVERY_50_MSECOND:
|
||||
callBerryFunctionVoid(PSTR("_run_deferred"));
|
||||
break;
|
||||
case FUNC_EVERY_100_MSECOND:
|
||||
callBerryFunctionVoid(PSTR("every_100ms"));
|
||||
break;
|
||||
case FUNC_EVERY_SECOND:
|
||||
callBerryFunctionVoid(PSTR("every_second"));
|
||||
callBerryEventDispatcher(PSTR("every_50ms"), nullptr, 0, nullptr);
|
||||
break;
|
||||
case FUNC_COMMAND:
|
||||
result = DecodeCommand(kBrCommands, BerryCommand);
|
||||
if (!result) {
|
||||
result = callBerryCommand();
|
||||
result = callBerryEventDispatcher(PSTR("cmd"), XdrvMailbox.topic, XdrvMailbox.index, XdrvMailbox.data);
|
||||
}
|
||||
break;
|
||||
|
||||
// Module specific events
|
||||
case FUNC_EVERY_100_MSECOND:
|
||||
callBerryEventDispatcher(PSTR("every_100ms"), nullptr, 0, nullptr);
|
||||
break;
|
||||
case FUNC_EVERY_SECOND:
|
||||
callBerryEventDispatcher(PSTR("every_second"), nullptr, 0, nullptr);
|
||||
break;
|
||||
// case FUNC_SET_POWER:
|
||||
// break;
|
||||
case FUNC_RULES_PROCESS:
|
||||
result = callBerryRule();
|
||||
break;
|
||||
#ifdef USE_WEBSERVER
|
||||
case FUNC_WEB_ADD_BUTTON:
|
||||
WSContentSend_P(HTTP_BTN_BERRY_CONSOLE);
|
||||
callBerryEventDispatcher(PSTR("web_add_button"), nullptr, 0, nullptr);
|
||||
break;
|
||||
case FUNC_WEB_ADD_MAIN_BUTTON:
|
||||
|
||||
callBerryEventDispatcher(PSTR("web_add_main_button"), nullptr, 0, nullptr);
|
||||
break;
|
||||
case FUNC_WEB_ADD_HANDLER:
|
||||
callBerryEventDispatcher(PSTR("web_add_handler"), nullptr, 0, nullptr);
|
||||
WebServer_on(PSTR("/bs"), HandleBerryConsole);
|
||||
break;
|
||||
#endif // USE_WEBSERVER
|
||||
case FUNC_SAVE_BEFORE_RESTART:
|
||||
break;
|
||||
case FUNC_MQTT_DATA:
|
||||
// callBerryMqttData();
|
||||
callBerryEventDispatcher(PSTR("save_before_restart"), nullptr, 0, nullptr);
|
||||
break;
|
||||
case FUNC_WEB_SENSOR:
|
||||
callBerryEventDispatcher(PSTR("web_sensor"), nullptr, 0, nullptr);
|
||||
break;
|
||||
|
||||
case FUNC_JSON_APPEND:
|
||||
callBerryEventDispatcher(PSTR("json_aooend"), nullptr, 0, nullptr);
|
||||
break;
|
||||
|
||||
case FUNC_BUTTON_PRESSED:
|
||||
callBerryEventDispatcher(PSTR("button_pressed"), nullptr, 0, nullptr);
|
||||
break;
|
||||
|
||||
|
||||
|
@ -42,7 +42,7 @@ uint8_t ili9342_ctouch_counter = 0;
|
||||
bool tft_init_done = false;
|
||||
|
||||
|
||||
//Settings.display_options.ilimode = ILIMODE_9341;
|
||||
//Settings.display_options.type = ILIMODE_9341;
|
||||
|
||||
/*********************************************************************************************/
|
||||
|
||||
@ -65,8 +65,8 @@ void ILI9341_InitDriver()
|
||||
// disable screen buffer
|
||||
buffer = NULL;
|
||||
|
||||
if (!Settings.display_options.ilimode || (Settings.display_options.ilimode >= ILIMODE_MAX)) {
|
||||
Settings.display_options.ilimode = ILIMODE_9341;
|
||||
if (!Settings.display_options.type || (Settings.display_options.type >= ILIMODE_MAX)) {
|
||||
Settings.display_options.type = ILIMODE_9341;
|
||||
}
|
||||
|
||||
// default colors
|
||||
@ -77,11 +77,11 @@ void ILI9341_InitDriver()
|
||||
if (TasmotaGlobal.soft_spi_enabled) {
|
||||
// Init renderer, may use hardware spi, however we use SSPI defintion because SD card uses SPI definition (2 spi busses)
|
||||
if (PinUsed(GPIO_SSPI_MOSI) && PinUsed(GPIO_SSPI_MISO) && PinUsed(GPIO_SSPI_SCLK)) {
|
||||
ili9341_2 = new ILI9341_2(Pin(GPIO_ILI9341_CS), Pin(GPIO_SSPI_MOSI), Pin(GPIO_SSPI_MISO), Pin(GPIO_SSPI_SCLK), Pin(GPIO_OLED_RESET), Pin(GPIO_ILI9341_DC), Pin(GPIO_BACKLIGHT), 2, Settings.display_options.ilimode & 3);
|
||||
ili9341_2 = new ILI9341_2(Pin(GPIO_ILI9341_CS), Pin(GPIO_SSPI_MOSI), Pin(GPIO_SSPI_MISO), Pin(GPIO_SSPI_SCLK), Pin(GPIO_OLED_RESET), Pin(GPIO_ILI9341_DC), Pin(GPIO_BACKLIGHT), 2, Settings.display_options.type & 3);
|
||||
}
|
||||
} else if (TasmotaGlobal.spi_enabled) {
|
||||
if (PinUsed(GPIO_ILI9341_DC)) {
|
||||
ili9341_2 = new ILI9341_2(Pin(GPIO_ILI9341_CS), Pin(GPIO_SPI_MOSI), Pin(GPIO_SPI_MISO), Pin(GPIO_SPI_CLK), Pin(GPIO_OLED_RESET), Pin(GPIO_ILI9341_DC), Pin(GPIO_BACKLIGHT), 1, Settings.display_options.ilimode & 3);
|
||||
ili9341_2 = new ILI9341_2(Pin(GPIO_ILI9341_CS), Pin(GPIO_SPI_MOSI), Pin(GPIO_SPI_MISO), Pin(GPIO_SPI_CLK), Pin(GPIO_OLED_RESET), Pin(GPIO_ILI9341_DC), Pin(GPIO_BACKLIGHT), 1, Settings.display_options.type & 3);
|
||||
}
|
||||
}
|
||||
|
||||
@ -101,7 +101,7 @@ void ILI9341_InitDriver()
|
||||
renderer->setTextFont(2);
|
||||
renderer->setTextSize(1);
|
||||
renderer->setTextColor(ILI9341_WHITE, ILI9341_BLACK);
|
||||
renderer->DrawStringAt(50, (Settings.display_height/2)-12, (Settings.display_options.ilimode & 3)==ILIMODE_9341?"ILI9341 TFT!":"ILI9342 TFT!", ILI9341_WHITE, 0);
|
||||
renderer->DrawStringAt(50, (Settings.display_height/2)-12, (Settings.display_options.type & 3)==ILIMODE_9341?"ILI9341 TFT!":"ILI9342 TFT!", ILI9341_WHITE, 0);
|
||||
delay(1000);
|
||||
#endif // SHOW_SPLASH
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -21,7 +21,7 @@
|
||||
#ifdef USE_CSE7761
|
||||
/*********************************************************************************************\
|
||||
* CSE7761 - Energy (Sonoff Dual R3 Pow)
|
||||
* {"NAME":"Sonoff Dual R3","GPIO":[0,0,1,0,0,0,3232,3200,0,0,225,0,0,0,0,0,0,0,0,0,1,7296,7328,224,0,0,0,0,160,161,0,0,0,0,0,0],"FLAG":0,"BASE":1}
|
||||
* {"NAME":"Sonoff Dual R3","GPIO":[32,0,0,0,0,0,0,0,0,576,225,0,0,0,0,0,0,0,0,0,0,7296,7328,224,0,0,0,0,160,161,0,0,0,0,0,0],"FLAG":0,"BASE":1}
|
||||
*
|
||||
* Based on datasheet from ChipSea and analysing serial data
|
||||
* See https://github.com/arendst/Tasmota/discussions/10793
|
||||
@ -34,29 +34,31 @@
|
||||
#define CSE7761_UREF 42563 // RmsUc
|
||||
#define CSE7761_IREF 52241 // RmsIAC
|
||||
#define CSE7761_PREF 44513 // PowerPAC
|
||||
#define CSE7761_FREF 3579545 // System clock (3.579545MHz) as used in frequency calculation
|
||||
|
||||
#define CSE7761_REG_SYSCON 0x00 // System Control Register
|
||||
#define CSE7761_REG_EMUCON 0x01 // Metering control register
|
||||
#define CSE7761_REG_EMUCON2 0x13 // Metering control register 2
|
||||
#define CSE7761_REG_SYSCON 0x00 // (2) System Control Register (0x0A04)
|
||||
#define CSE7761_REG_EMUCON 0x01 // (2) Metering control register (0x0000)
|
||||
#define CSE7761_REG_EMUCON2 0x13 // (2) Metering control register 2 (0x0001)
|
||||
|
||||
#define CSE7761_REG_UFREQ 0x23 // Voltage Frequency Register
|
||||
#define CSE7761_REG_RMSIA 0x24 // The effective value of channel A current
|
||||
#define CSE7761_REG_RMSIB 0x25 // The effective value of channel B current
|
||||
#define CSE7761_REG_RMSU 0x26 // Voltage RMS
|
||||
#define CSE7761_REG_POWERPA 0x2C // Channel A active power, update rate 27.2Hz
|
||||
#define CSE7761_REG_POWERPB 0x2D // Channel B active power, update rate 27.2Hz
|
||||
#define CSE7761_REG_SYSSTATUS 0x43 // System status register
|
||||
#define CSE7761_REG_UFREQ 0x23 // (2) Voltage Frequency (0x0000)
|
||||
#define CSE7761_REG_RMSIA 0x24 // (3) The effective value of channel A current (0x000000)
|
||||
#define CSE7761_REG_RMSIB 0x25 // (3) The effective value of channel B current (0x000000)
|
||||
#define CSE7761_REG_RMSU 0x26 // (3) Voltage RMS (0x000000)
|
||||
#define CSE7761_REG_POWERFACTOR 0x27 // (3) Power factor register, select by command: channel A Power factor or channel B power factor (0x7FFFFF)
|
||||
#define CSE7761_REG_POWERPA 0x2C // (4) Channel A active power, update rate 27.2Hz (0x00000000)
|
||||
#define CSE7761_REG_POWERPB 0x2D // (4) Channel B active power, update rate 27.2Hz (0x00000000)
|
||||
#define CSE7761_REG_SYSSTATUS 0x43 // (1) System status register
|
||||
|
||||
#define CSE7761_REG_COEFFOFFSET 0x6E // Coefficient checksum offset (0xFFFF)
|
||||
#define CSE7761_REG_COEFFCHKSUM 0x6F // Coefficient checksum
|
||||
#define CSE7761_REG_RMSIAC 0x70 // Channel A effective current conversion coefficient
|
||||
#define CSE7761_REG_RMSIBC 0x71 // Channel B effective current conversion coefficient
|
||||
#define CSE7761_REG_RMSUC 0x72 // Effective voltage conversion coefficient
|
||||
#define CSE7761_REG_POWERPAC 0x73 // Channel A active power conversion coefficient
|
||||
#define CSE7761_REG_POWERPBC 0x74 // Channel B active power conversion coefficient
|
||||
#define CSE7761_REG_POWERSC 0x75 // Apparent power conversion coefficient
|
||||
#define CSE7761_REG_ENERGYAC 0x76 // Channel A energy conversion coefficient
|
||||
#define CSE7761_REG_ENERGYBC 0x77 // Channel B energy conversion coefficient
|
||||
#define CSE7761_REG_COEFFOFFSET 0x6E // (2) Coefficient checksum offset (0xFFFF)
|
||||
#define CSE7761_REG_COEFFCHKSUM 0x6F // (2) Coefficient checksum
|
||||
#define CSE7761_REG_RMSIAC 0x70 // (2) Channel A effective current conversion coefficient
|
||||
#define CSE7761_REG_RMSIBC 0x71 // (2) Channel B effective current conversion coefficient
|
||||
#define CSE7761_REG_RMSUC 0x72 // (2) Effective voltage conversion coefficient
|
||||
#define CSE7761_REG_POWERPAC 0x73 // (2) Channel A active power conversion coefficient
|
||||
#define CSE7761_REG_POWERPBC 0x74 // (2) Channel B active power conversion coefficient
|
||||
#define CSE7761_REG_POWERSC 0x75 // (2) Apparent power conversion coefficient
|
||||
#define CSE7761_REG_ENERGYAC 0x76 // (2) Channel A energy conversion coefficient
|
||||
#define CSE7761_REG_ENERGYBC 0x77 // (2) Channel B energy conversion coefficient
|
||||
|
||||
#define CSE7761_SPECIAL_COMMAND 0xEA // Start special command
|
||||
#define CSE7761_CMD_RESET 0x96 // Reset command, after receiving the command, the chip resets
|
||||
@ -76,6 +78,7 @@ enum CSE7761 { RmsIAC, RmsIBC, RmsUC, PowerPAC, PowerPBC, PowerSC, EnergyAC, Ene
|
||||
TasmotaSerial *Cse7761Serial = nullptr;
|
||||
|
||||
struct {
|
||||
uint32_t frequency = 0;
|
||||
uint32_t voltage_rms = 0;
|
||||
uint32_t current_rms[2] = { 0 };
|
||||
uint32_t energy[2] = { 0 };
|
||||
@ -114,7 +117,7 @@ void Cse7761Write(uint32_t reg, uint32_t data) {
|
||||
AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("C61: Tx %*_H"), len, buffer);
|
||||
}
|
||||
|
||||
uint32_t Cse7761Read(uint32_t reg, uint32_t size) {
|
||||
bool Cse7761ReadOnce(uint32_t log_level, uint32_t reg, uint32_t size, uint32_t* value) {
|
||||
while (Cse7761Serial->available()) { Cse7761Serial->read(); }
|
||||
|
||||
Cse7761Write(reg, 0);
|
||||
@ -123,8 +126,8 @@ uint32_t Cse7761Read(uint32_t reg, uint32_t size) {
|
||||
uint32_t rcvd = 0;
|
||||
uint32_t timeout = millis() + 3;
|
||||
|
||||
// while (!TimeReached(timeout) && (rcvd <= size)) {
|
||||
while (!TimeReached(timeout)) {
|
||||
while (!TimeReached(timeout) && (rcvd <= size)) {
|
||||
// while (!TimeReached(timeout)) {
|
||||
int value = Cse7761Serial->read();
|
||||
if ((value > -1) && (rcvd < sizeof(buffer) -1)) {
|
||||
buffer[rcvd++] = value;
|
||||
@ -133,12 +136,12 @@ uint32_t Cse7761Read(uint32_t reg, uint32_t size) {
|
||||
|
||||
if (!rcvd) {
|
||||
AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("C61: Rx none"));
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("C61: Rx %*_H"), rcvd, buffer);
|
||||
if (rcvd > 5) {
|
||||
AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("C61: Rx overflow"));
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
rcvd--;
|
||||
@ -150,16 +153,28 @@ uint32_t Cse7761Read(uint32_t reg, uint32_t size) {
|
||||
}
|
||||
crc = ~crc;
|
||||
if (crc != buffer[rcvd]) {
|
||||
AddLog(LOG_LEVEL_DEBUG, PSTR("C61: Rx %*_H, CRC error %02X"), rcvd +1, buffer, crc);
|
||||
return 1;
|
||||
AddLog(log_level, PSTR("C61: Rx %*_H, CRC error %02X"), rcvd +1, buffer, crc);
|
||||
return false;
|
||||
}
|
||||
|
||||
return result;
|
||||
*value = result;
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32_t Cse7761Read(uint32_t reg, uint32_t size) {
|
||||
bool result = false; // Start loop
|
||||
uint32_t retry = 3; // Retry up to three times
|
||||
uint32_t value = 0; // Default no value
|
||||
while (!result && retry) {
|
||||
retry--;
|
||||
result = Cse7761ReadOnce((retry) ? LOG_LEVEL_DEBUG_MORE : LOG_LEVEL_DEBUG, reg, size, &value);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
uint32_t Cse7761ReadFallback(uint32_t reg, uint32_t prev, uint32_t size) {
|
||||
uint32_t value = Cse7761Read(reg, size);
|
||||
if (1 == value) { // CRC Error so use previous value read
|
||||
if (!value) { // Error so use previous value read
|
||||
value = prev;
|
||||
}
|
||||
return value;
|
||||
@ -192,16 +207,21 @@ bool Cse7761ChipInit(void) {
|
||||
// CSE7761Data.coefficient[PowerPBC] = 0xADD7;
|
||||
}
|
||||
if (HLW_PREF_PULSE == Settings.energy_power_calibration) {
|
||||
Settings.energy_frequency_calibration = CSE7761_FREF;
|
||||
Settings.energy_voltage_calibration = Cse7761Ref(RmsUC);
|
||||
Settings.energy_current_calibration = Cse7761Ref(RmsIAC);
|
||||
Settings.energy_power_calibration = Cse7761Ref(PowerPAC);
|
||||
}
|
||||
// Just to fix intermediate users
|
||||
if (Settings.energy_frequency_calibration < CSE7761_FREF / 2) {
|
||||
Settings.energy_frequency_calibration = CSE7761_FREF;
|
||||
}
|
||||
|
||||
Cse7761Write(CSE7761_SPECIAL_COMMAND, CSE7761_CMD_ENABLE_WRITE);
|
||||
|
||||
// delay(8); // Exception on ESP8266
|
||||
uint32_t timeout = millis() + 8;
|
||||
while (!TimeReached(timeout)) { }
|
||||
// uint32_t timeout = millis() + 8;
|
||||
// while (!TimeReached(timeout)) { }
|
||||
|
||||
uint8_t sys_status = Cse7761Read(CSE7761_REG_SYSSTATUS, 1);
|
||||
#ifdef CSE7761_SIMULATE
|
||||
@ -310,7 +330,7 @@ bool Cse7761ChipInit(void) {
|
||||
=1, turn on the power factor output function (Sonoff Dual R3 Pow)
|
||||
=0, turn off the power factor output function
|
||||
5 WaveEN Waveform data, instantaneous data output enable signal
|
||||
=1, turn on the waveform data output function
|
||||
=1, turn on the waveform data output function (Tasmota add frequency)
|
||||
=0, turn off the waveform data output function (Sonoff Dual R3 Pow)
|
||||
4 SAGEN Voltage drop detection enable signal, WaveEN=1 must be configured first
|
||||
=1, turn on the voltage drop detection function
|
||||
@ -319,14 +339,15 @@ bool Cse7761ChipInit(void) {
|
||||
=1, turn on the overvoltage, overcurrent, and overload detection functions
|
||||
=0, turn off the overvoltage, overcurrent, and overload detection functions (Sonoff Dual R3 Pow)
|
||||
2 ZxEN Zero-crossing detection, phase angle, voltage frequency measurement enable signal
|
||||
=1, turn on the zero-crossing detection, phase angle, and voltage frequency measurement functions
|
||||
=1, turn on the zero-crossing detection, phase angle, and voltage frequency measurement functions (Tasmota add frequency)
|
||||
=0, disable zero-crossing detection, phase angle, voltage frequency measurement functions (Sonoff Dual R3 Pow)
|
||||
1 PeakEN Peak detect enable signal
|
||||
=1, turn on the peak detection function
|
||||
=0, turn off the peak detection function (Sonoff Dual R3 Pow)
|
||||
0 NC Default is 1
|
||||
*/
|
||||
Cse7761Write(CSE7761_REG_EMUCON2 | 0x80, 0x0FC1);
|
||||
// Cse7761Write(CSE7761_REG_EMUCON2 | 0x80, 0x0FC1); // Sonoff Dual R3 Pow
|
||||
Cse7761Write(CSE7761_REG_EMUCON2 | 0x80, 0x0FE5); // Tasmota add Frequency
|
||||
} else {
|
||||
AddLog(LOG_LEVEL_DEBUG, PSTR("C61: Write failed"));
|
||||
return false;
|
||||
@ -344,6 +365,12 @@ void Cse7761GetData(void) {
|
||||
#endif
|
||||
CSE7761Data.voltage_rms = (value >= 0x800000) ? 0 : value;
|
||||
|
||||
value = Cse7761ReadFallback(CSE7761_REG_UFREQ, CSE7761Data.frequency, 2);
|
||||
#ifdef CSE7761_SIMULATE
|
||||
value = 8948; // 49.99Hz
|
||||
#endif
|
||||
CSE7761Data.frequency = (value >= 0x8000) ? 0 : value;
|
||||
|
||||
value = Cse7761ReadFallback(CSE7761_REG_RMSIA, CSE7761Data.current_rms[0], 3);
|
||||
#ifdef CSE7761_SIMULATE
|
||||
value = 455;
|
||||
@ -366,8 +393,8 @@ void Cse7761GetData(void) {
|
||||
#endif
|
||||
CSE7761Data.active_power[1] = (0 == CSE7761Data.current_rms[1]) ? 0 : (value & 0x80000000) ? (~value) + 1 : value;
|
||||
|
||||
AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("C61: U%d, I%d/%d, P%d/%d"),
|
||||
CSE7761Data.voltage_rms,
|
||||
AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("C61: F%d, U%d, I%d/%d, P%d/%d"),
|
||||
CSE7761Data.frequency, CSE7761Data.voltage_rms,
|
||||
CSE7761Data.current_rms[0], CSE7761Data.current_rms[1],
|
||||
CSE7761Data.active_power[0], CSE7761Data.active_power[1]);
|
||||
|
||||
@ -375,6 +402,7 @@ void Cse7761GetData(void) {
|
||||
// Voltage = RmsU * RmsUC * 10 / 0x400000
|
||||
// Energy.voltage[0] = (float)(((uint64_t)CSE7761Data.voltage_rms * CSE7761Data.coefficient[RmsUC] * 10) >> 22) / 1000; // V
|
||||
Energy.voltage[0] = ((float)CSE7761Data.voltage_rms / Settings.energy_voltage_calibration); // V
|
||||
Energy.frequency[0] = (CSE7761Data.frequency) ? ((float)Settings.energy_frequency_calibration / 8 / CSE7761Data.frequency) : 0; // Hz
|
||||
|
||||
for (uint32_t channel = 0; channel < 2; channel++) {
|
||||
Energy.data_valid[channel] = 0;
|
||||
@ -460,6 +488,7 @@ void Cse7761DrvInit(void) {
|
||||
CSE7761Data.init = 4; // Init setup steps
|
||||
Energy.phase_count = 2; // Handle two channels as two phases
|
||||
Energy.voltage_common = true; // Use common voltage
|
||||
Energy.frequency_common = true; // Use common frequency
|
||||
TasmotaGlobal.energy_driver = XNRG_19;
|
||||
}
|
||||
}
|
||||
@ -482,6 +511,10 @@ bool Cse7761Command(void) {
|
||||
if (1 == XdrvMailbox.payload) { XdrvMailbox.payload = Cse7761Ref(RmsIAC); }
|
||||
// Service in xdrv_03_energy.ino
|
||||
}
|
||||
else if (CMND_FREQUENCYCAL == Energy.command_code) {
|
||||
if (1 == XdrvMailbox.payload) { XdrvMailbox.payload = CSE7761_FREF; }
|
||||
// Service in xdrv_03_energy.ino
|
||||
}
|
||||
else if (CMND_POWERSET == Energy.command_code) {
|
||||
if (XdrvMailbox.data_len && CSE7761Data.active_power[channel]) {
|
||||
if ((value > 100) && (value < 200000)) { // Between 1W and 2000W
|
||||
@ -503,6 +536,13 @@ bool Cse7761Command(void) {
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (CMND_FREQUENCYSET == Energy.command_code) {
|
||||
if (XdrvMailbox.data_len && CSE7761Data.frequency) {
|
||||
if ((value > 4500) && (value < 6500)) { // Between 45.00Hz and 65.00Hz
|
||||
Settings.energy_frequency_calibration = (CSE7761Data.frequency * 8 * value) / 100;
|
||||
}
|
||||
}
|
||||
}
|
||||
else serviced = false; // Unknown command
|
||||
|
||||
return serviced;
|
||||
|
@ -113,7 +113,6 @@ const char* ConvertNumTxt(uint8_t statu, uint8_t pinmod=0) {
|
||||
#endif // USE_MCP230xx_OUTPUT
|
||||
#ifdef USE_MCP230xx_OUTPUT
|
||||
if ((6 == pinmod) && (statu < 2)) { statu = 1-statu; }
|
||||
AddLog(LOG_LEVEL_DEBUG, PSTR("MCP: ConvertNumTxt config=%d save_state=%d"),config, Settings.flag.save_state);
|
||||
if ((config) && (Settings.flag.save_state)) {
|
||||
return "SAVED";
|
||||
}
|
||||
@ -205,7 +204,6 @@ void MCP230xx_ApplySettings(void)
|
||||
reg_portpins[mcp230xx_port] |= (Settings.mcp230xx_config[idx+(mcp230xx_port*8)].saved_state << idx);
|
||||
} else {
|
||||
if (Settings.mcp230xx_config[idx+(mcp230xx_port*8)].keep_output) { // Read the value to use from the MCP230xx
|
||||
AddLog(LOG_LEVEL_DEBUG, PSTR("MCP: readpins=%d or_val=%d"),reg_readpins, reg_readpins & (1 << idx));
|
||||
reg_portpins[mcp230xx_port] |= reg_readpins & (1 << idx);
|
||||
}
|
||||
else if (Settings.mcp230xx_config[idx+(mcp230xx_port*8)].pullup) {
|
||||
|
@ -43,6 +43,7 @@
|
||||
* - added SetOption123 0-Wiegand UID decimal (default) 1-Wiegand UID hexadecimal
|
||||
* - added SetOption124 0-all keys up to ending char (# or *) send as one tag by MQTT (default) 1-Keypad every key a single tag
|
||||
* - added a new realtime testing option emulating a Wiegang reader output on same GPIOs where normally reader is attached. Details below
|
||||
* - fix timing issue when fast glitches are detected on one on the datalines. The interbitgab was too short in that case
|
||||
\*********************************************************************************************/
|
||||
#pragma message("**** Wiegand interface enabled ****")
|
||||
|
||||
@ -106,10 +107,12 @@ class Wiegand {
|
||||
bool WiegandConversion (uint64_t , uint16_t );
|
||||
void setOutputFormat(void); // fix output HEX format
|
||||
void HandleKeyPad(void); //handle one tag for multi key strokes
|
||||
|
||||
|
||||
static void handleD0Interrupt(void);
|
||||
static void handleD1Interrupt(void);
|
||||
static void handleDxInterrupt(int in); // fix #11047
|
||||
static void ClearRFIDBuffer(int);
|
||||
|
||||
uint64_t rfid;
|
||||
uint32_t tagSize;
|
||||
@ -142,6 +145,58 @@ volatile bool Wiegand::CodeComplete;
|
||||
volatile RFID_store Wiegand::rfid_found[WIEGAND_RFID_ARRAY_SIZE];
|
||||
volatile int Wiegand::currentFoundRFIDcount;
|
||||
|
||||
|
||||
|
||||
void ICACHE_RAM_ATTR Wiegand::ClearRFIDBuffer(int endIndex = WIEGAND_RFID_ARRAY_SIZE) {
|
||||
currentFoundRFIDcount=WIEGAND_RFID_ARRAY_SIZE-endIndex; // clear all buffers
|
||||
for (int i= 0; i < endIndex; i++) {
|
||||
rfid_found[i].RFID=0;
|
||||
rfid_found[i].bitCount=0;
|
||||
}
|
||||
}
|
||||
void ICACHE_RAM_ATTR Wiegand::handleD1Interrupt() { // Receive a 1 bit. (D0=high & D1=low)
|
||||
handleDxInterrupt(1);
|
||||
}
|
||||
|
||||
void ICACHE_RAM_ATTR Wiegand::handleD0Interrupt() { // Receive a 0 bit. (D0=low & D1=high)
|
||||
handleDxInterrupt(0);
|
||||
}
|
||||
|
||||
void ICACHE_RAM_ATTR Wiegand::handleDxInterrupt(int in) {
|
||||
unsigned long curTime = micros(); // to be sure I will use micros() instead of millis() overflow is handle by using the minus operator to compare
|
||||
unsigned long diffTime= curTime - lastFoundTime;
|
||||
if ( (diffTime > CodeGapTime) && (bitCount > 0)) {
|
||||
// previous RFID tag (key pad numer)is complete. Will be detected by the code ending gap
|
||||
// one bit will take the time of impulse_time + impulse_gap_time. it (bitTime) will be recalculated each time an impulse is detected
|
||||
// the devices will add some inter_code_gap_time to separate codes this will be much longer than the bit_time. (WIEGAND_CODE_GAP_FACTOR)
|
||||
// unfortunately there's no timing defined for Wiegand. On my test reader the impulse time = 125 µs impulse gap time = 950 µs.
|
||||
if (currentFoundRFIDcount < WIEGAND_RFID_ARRAY_SIZE) { // when reaching the end of rfid buffer we will overwrite the last one.
|
||||
currentFoundRFIDcount++;
|
||||
}
|
||||
// start a new tag
|
||||
rfidBuffer = 0;
|
||||
bitCount = 0;
|
||||
FirstBitTimeStamp = 0;
|
||||
}
|
||||
|
||||
if (in == 0) { rfidBuffer = rfidBuffer << 1; } // Receive a 0 bit. (D0=low & D1=high): Leftshift the 0 bit is now at the end of rfidBuffer
|
||||
else if (in == 1) {rfidBuffer = (rfidBuffer << 1) | 1; } // Receive a 1 bit. (D0=high & D1=low): Leftshift + 1 bit
|
||||
else { return; } // (in==3) called by ScanForTag to get the last tag, because the interrupt handler is no longer called after receiving the last bit
|
||||
|
||||
bitCount++;
|
||||
if (bitCount == 1) { // first bit was detected
|
||||
FirstBitTimeStamp = (curTime != 0) ? curTime : 1; // accept 1µs differenct to avoid a miss the first timestamp if curTime is 0.
|
||||
}
|
||||
else if (bitCount == 2) { // only calculate once per RFID tag, but restrict to values, which are in within a plausible range
|
||||
bitTime = ((diffTime > (WIEGAND_BIT_TIME_DEFAULT/4)) && (diffTime < (4*WIEGAND_BIT_TIME_DEFAULT))) ? diffTime : WIEGAND_BIT_TIME_DEFAULT;
|
||||
CodeGapTime = WIEGAND_CODE_GAP_FACTOR * bitTime;
|
||||
}
|
||||
//save current rfid in array otherwise we will never see the last found tag
|
||||
rfid_found[currentFoundRFIDcount].RFID=rfidBuffer;
|
||||
rfid_found[currentFoundRFIDcount].bitCount= bitCount;
|
||||
lastFoundTime = curTime; // Last time a bit was detected
|
||||
}
|
||||
|
||||
Wiegand::Wiegand() {
|
||||
rfid = 0;
|
||||
lastFoundTime = 0;
|
||||
@ -154,67 +209,12 @@ Wiegand::Wiegand() {
|
||||
FirstBitTimeStamp = 0;
|
||||
CodeGapTime = WIEGAND_CODE_GAP_FACTOR * bitTime;
|
||||
CodeComplete = false;
|
||||
currentFoundRFIDcount=0;
|
||||
for (int i=0; i < WIEGAND_RFID_ARRAY_SIZE; i++ )
|
||||
{
|
||||
rfid_found[i].RFID=0;
|
||||
rfid_found[i].bitCount=0;
|
||||
}
|
||||
ClearRFIDBuffer();
|
||||
outFormat="u"; // standard output format decimal
|
||||
mqttRFIDKeypadBuffer = 0;
|
||||
webRFIDKeypadBuffer = 0;
|
||||
}
|
||||
|
||||
void ICACHE_RAM_ATTR Wiegand::handleD1Interrupt() { // Receive a 1 bit. (D0=high & D1=low)
|
||||
handleDxInterrupt(1);
|
||||
}
|
||||
|
||||
void ICACHE_RAM_ATTR Wiegand::handleD0Interrupt() { // Receive a 0 bit. (D0=low & D1=high)
|
||||
handleDxInterrupt(0);
|
||||
}
|
||||
|
||||
void ICACHE_RAM_ATTR Wiegand::handleDxInterrupt(int in) {
|
||||
|
||||
unsigned long curTime = micros(); // to be sure I will use micros() instead of millis() overflow is handle by using the minus operator to compare
|
||||
unsigned long diffTime= curTime - lastFoundTime;
|
||||
if (diffTime > 3000000 ) { //cancel noisy bits in buffer and start a new tag
|
||||
rfidBuffer = 0;
|
||||
bitCount = 0;
|
||||
FirstBitTimeStamp = 0;
|
||||
}
|
||||
if ( (diffTime > CodeGapTime) && (bitCount > 0)) {
|
||||
// previous RFID tag (key pad numer)is complete. Will be detected by the code ending gap
|
||||
// one bit will take the time of impulse_time + impulse_gap_time. it (bitTime) will be recalculated each time an impulse is detected
|
||||
// the devices will add some inter_code_gap_time to separate codes this will be much longer than the bit_time. (WIEGAND_CODE_GAP_FACTOR)
|
||||
// unfortunately there's no timing defined for Wiegang. On my test reader the impulse time = 125 µs impulse gap time = 950 µs.
|
||||
if (currentFoundRFIDcount < WIEGAND_RFID_ARRAY_SIZE) { // when reaching the end of rfid buffer we will overwrite the last one.
|
||||
currentFoundRFIDcount++;
|
||||
}
|
||||
// start a new tag
|
||||
rfidBuffer = 0;
|
||||
bitCount = 0;
|
||||
FirstBitTimeStamp = 0;
|
||||
}
|
||||
if (in ==3) {// called by ScanForTag to get the last tag, because the interrupt handler is no longer called after receiving the last bit
|
||||
return;
|
||||
}
|
||||
if (in == 0) { rfidBuffer = rfidBuffer << 1; } // Receive a 0 bit. (D0=low & D1=high): Leftshift the 0 bit is now at the end of rfidBuffer
|
||||
else {rfidBuffer = (rfidBuffer << 1) | 1; } // Receive a 1 bit. (D0=high & D1=low): Leftshift + 1 bit
|
||||
|
||||
bitCount++;
|
||||
if (bitCount == 1) { // first bit was detected
|
||||
FirstBitTimeStamp = (curTime != 0) ? curTime : 1; // accept 1µs differenct to avoid a miss the first timestamp if curTime is 0.
|
||||
}
|
||||
else if (bitCount == 2) { // only calculate once per RFID tag
|
||||
bitTime = diffTime; //calc maximum current length of one bit
|
||||
CodeGapTime = WIEGAND_CODE_GAP_FACTOR * bitTime;
|
||||
}
|
||||
//save current rfid in array otherwise we will never see the last found tag
|
||||
rfid_found[currentFoundRFIDcount].RFID=rfidBuffer;
|
||||
rfid_found[currentFoundRFIDcount].bitCount= bitCount;
|
||||
lastFoundTime = curTime; // Last time a bit was detected
|
||||
}
|
||||
|
||||
void Wiegand::Init() {
|
||||
isInit = false;
|
||||
if (PinUsed(GPIO_WIEGAND_D0) && PinUsed(GPIO_WIEGAND_D1)) { // Only start, if the Wiegang pins are selected
|
||||
@ -400,7 +400,7 @@ void Wiegand::ScanForTag() {
|
||||
uint64_t oldTag = rfid;
|
||||
bool validKey = WiegandConversion(rfid_found[i].RFID, rfid_found[i].bitCount);
|
||||
#if (DEV_WIEGAND_TEST_MODE)>0
|
||||
AddLog(LOG_LEVEL_INFO, PSTR("WIE: Previous tag %llu"), oldTag);
|
||||
AddLog(LOG_LEVEL_INFO, PSTR("WIE: ValidKey: %d Previous tag %llu"), validKey, oldTag);
|
||||
#endif // DEV_WIEGAND_TEST_MODE>0
|
||||
if (validKey) { // Only in case of valid key do action. Issue#10585
|
||||
HandleKeyPad(); //support one tag for multi key input
|
||||
@ -412,15 +412,14 @@ void Wiegand::ScanForTag() {
|
||||
MqttPublishTeleSensor();
|
||||
}
|
||||
}
|
||||
rfid_found[i].RFID=0;
|
||||
rfid_found[i].bitCount=0;
|
||||
}
|
||||
}
|
||||
if (currentFoundRFIDcount > lastFoundRFIDcount) {
|
||||
// if that happens: we need to move the id found during the loop to top of the array
|
||||
// and correct the currentFoundRFIDcount
|
||||
AddLog(LOG_LEVEL_INFO, PSTR("WIE: ScanForTag() %lu tags added while working on buffer"), (currentFoundRFIDcount-lastFoundRFIDcount));
|
||||
}
|
||||
currentFoundRFIDcount=0; //reset array
|
||||
ClearRFIDBuffer(); //reset array
|
||||
#if (DEV_WIEGAND_TEST_MODE)>0
|
||||
AddLog(LOG_LEVEL_INFO, PSTR("WIE: ScanForTag() time elapsed %lu"), (micros() - startTime));
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user