Updated Sensor API (markdown)

andrethomas 2018-09-26 20:19:25 +02:00
parent d34f5abe0e
commit bdb52388e9
1 changed files with 36 additions and 9 deletions

@ -59,8 +59,6 @@ boolean Xsns<driverID>(byte callback_id) {
break;
case FUNC_EVERY_SECOND:
break;
case FUNC_PREP_BEFORE_TELEPERIOD:
break;
case FUNC_JSON_APPEND:
break;
#ifdef USE_WEBSERVER
@ -80,7 +78,6 @@ boolean Xsns<driverID>(byte callback_id) {
#endif // USE_<driver_name>
```
## Callback IDs
### FUNC_INIT
@ -92,10 +89,7 @@ This callback ID is called every 50 milliseconds, e.g. for near real-time operat
### FUNC_EVERY_SECOND
This callback ID is called every second.
### FUNC_PREP_BEFORE_TELEPERIOD
NOTE: This callback ID is deprecated as sensors should prepare for more regular updates due to "realtime" rule execution. Use FUNC_EVERY_SECOND instead. See examples used in xsns_05_ds18x20.ino and xsns_09_bmp.ino where updated sensor data is stored in preparation to calls to FUNC_JSON_APPEND and FUNC_WEB_APPEND.
This callback ID is called before TELEPERIOD and is intended to make provision for your sensor to be ready for polling during FUNC_JSON_APPEND or FUNC_WEB_APPEND for example, amongst the other function call options used by your sensor in the boolean Xsns<driverID>(byte callback_id) function as referenced above.
It can be useful for anything that you need to do on a per second basis and is commonly used as an entry point to detect a driver or initialize an externally driven device such as a sensor, relay board or other forms of input/output required by your driver.
You would normally want to make sure you've detected and initialised before it is used by JSON_APPEND etc so that its ready to serve data.
@ -118,6 +112,21 @@ void MySensorDetect()
}
```
Setting a flag that the driver was successful in detecting the attached chip/board via I2C or SPI will prevent it from continuously trying to initialize an already initialized device.
When writing your function responsible for detecting an externally connected I2C device try to create a method by which you read or write to specific registers that would be applicable to that specific I2C device only as to confirm a positive detect for the device. If this is not done extensively it will lead to some drivers getting false detects for a different device type simply because it shares the same I2C address.
Unless your driver is specifically going to use the entire array of addresses provisioned by the manufacturer please consider using a #define USE_MYCHIPNAME_ADDR in the user_config.h so that the user may specify the address on which to expect the device. This is of course only applicable to drivers that are not enabled by default in any of the pre-built binaries.
**Four advanced methods to use FUNC_EVERY_SECOND (Food for thought) :**
* If a sensor needs an action which takes a long time, like more than 100mS, the action will be started here for a future follow-up. Using the uptime variable for testing like (uptime &1) will happen every 2 seconds. An example is the DS18B20 driver where readings (conversions they call it) can take up to 800mS from the initial request.
* If a sensor needed the previous action it is now time to gather the information and store it in a safe place to be used by FUNC_JSON_APPEND and/or FUNC_WEB_APPEND. Using the else function of the previous test (uptime &1) will happen every 2 seconds too but just 1 second later than the previous action.
* If a sensor does not respond for 10 times the sensor detection flag could be reset which will stop further processing until the sensor is re-detected. This is currently not being used actively as some users complain about disappearing sensors for whatever reason - Could be hardware related but easier to make Tasmota a little more flexible.
* Making re-dection of a sensor possible by executing this once every 100 seconds (94 == (uptime %100)) a re-attached sensor can be detected without a restart of Tasmota. The 94 given in this example should be different for every sensor driver to make sure not all sensors start detection at the same time. Using the drivers index number should be a good starting point.
### FUNC_PREP_BEFORE_TELEPERIOD
NOTE: This callback ID is deprecated as sensors should prepare for more regular updates due to "realtime" rule execution. Use FUNC_EVERY_SECOND instead. See examples used in xsns_05_ds18x20.ino and xsns_09_bmp.ino where updated sensor data is stored in preparation to calls to FUNC_JSON_APPEND and FUNC_WEB_APPEND.
### FUNC_JSON_APPEND
This callback ID is called when `TELEPERIOD` is due to append telemetry data to the MQTT JSON string or at approximately every 2 seconds when a rule is checked, e.g.
```
@ -135,7 +144,7 @@ It should be wrapped in `#ifdef USE_WEBSERVER ... #endif // USE_WEBSERVER`
This callback ID is called to allow a sensor to prepare for saving configuration changes. To be used to save volatile data just before a restart. Variables can be appended to `struct SYSCFG {} Settings` in file `sonoff/settings.h`.
### FUNC_COMMAND
This callback ID is called when a sensor specific command ``Sensor<xx>`` is executed where xx is the sensor index.
This callback ID is called when a sensor specific command ``Sensor<xx>`` or ``Driver<xx>`` is executed where xx is the sensor index.
```
case FUNC_COMMAND:
if (XSNS_<driver_ID> == XdrvMailbox.index) {
@ -159,6 +168,24 @@ struct XDRVMAILBOX {
} XdrvMailbox;
```
If your driver needs to accept multiple parameters for SensorXX and/or DriverXX please consider using comma delimited formatting and use the already written subStr() function declared in support.ino to parse throuhg the parameters you need.
An example of those could be
```
sensorXX reset // The reset parameter may be intercepted using:
if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 1),"RESET")) { // Note 1 used for param number
MyDriverName_Reset();
return serviced;
}
```
Or in the case of multiple parameters
```
sensorXX mode,1
if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 1),"RESET")) { // Note 1 used for param number
uint8_t mode = atoi(subStr(sub_string, XdrvMailbox.data, ",", 2); // Note 2 used for param number
}
```
## Useful functions
### MQTT
@ -196,7 +223,7 @@ ___
#### bool I2cValidRead(uint8_t addr, uint8_t reg, uint8_t size)
These functions return `true` if 1, 2, 3 or `size` bytes can be read from the I2C address `addr` and register `reg` into `*data`.
Functions with a `S` read signed data types while functions without a `S` read unsigned data types.
Functions with LE read little endian byte order while functions without LE read machine byte order.
Functions with LE read little-endian byte order while functions without LE read machine byte order.
#### uint8_t I2cRead8(uint8_t addr, uint8_t reg)
#### uint16_t I2cRead16(uint8_t addr, uint8_t reg)