Rather than auto-enable OTA if not already enabled in safemode, changed the logic to simply rollback to previous app if OTA was used to download a sketch that does not itself have OTA enabled, unless OTA was previously enabled without safemode.
To do: Delete all complicated SpanOTA logic that (unsuccessfully) tried to track OTA status and check SHA246 partition codes to determine if reboot was OTA or Serial. None of this is need, but some of the code may be useful for other things in the future.
Since much of the Arduino-ESP32 library is precompiled, you cannot use -DCONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE to define this during compile time (it gets defined but is not used by the precompiled libraries).
TO DO: create an NVS entry that flags whether last update was via OTA. If so, automatically enable OTA regardless of enableOTA setting. This would ensure that OTA cannot be disabled accidentally by uploading a non-enabledOTA sketch to remote device.
Callback function must be of type void()(boolean isPaired). Will be called when device is paired and when device is unpaired. Allows for user-defineable actions upon device pairing/unpairing.
The update from Arduino-ESP32 2.0.0 to 2.0.1 contained significant changes to the structures used by the IDF for generic timers. This broke the Blinker code (would not compile for ESP32-S2 and C3 chips).
The solution: Modified Blinker::isrTimer() to use a *generic* interrupt-clearing function when available (IDF version >= 4.0.0). Below 4.0.0 the code continues to manually clear the interrupt flag by resetting specific structure variables, though the logic is simpler since this is only needed for the ESP32 chip (the S2 and C3 are not supported in earlier versions of Arduino-ESP32).
This provides for full compatibility with Arduino-ESP32 versions 2.0.1, 2.0.0, and 1.0.6. The use of a generic interrupt clearing function when IDF>=4.0.0 will hopefully make this future-proof to any further changes by Espressif to the underlying timer structures.
This returns a vector of linked Services that can be used in a for-each loop as such:
for(auto services : getLinks()){ ... }
Must cast services into specific Service type to access anything not generic to the SpanService class
And also converted ERRORS to WARNINGS when a Characteristic that is not in the REQ or OPT list is specified for a Service. This allows the user to add any Characteristic to any Service without forcing an Error (just a Warning).
Ranges are now checked for all Characteristics at the end of the configuration, instead of at the end of each Accessory definition. This is much cleaner and the output is easier to read.
To do: Revisit use of REQ and OPT - what should constitute a fatal error and what should be a warning.
To do: Revisit Character definitions - attempt to normalize using the methods implemented for Custom Characteristics
No need to specify both FORMAT and TYPE. For example, specifying UINT16 automatically sets type to be uint16_t.
To do: Explore if this can be used for standard Characteristics - revisit standard Characteristics definitions and structure to see if it can be simplified.
Arduino-ESP32 has modified the Mbed TLS library so that it uses ESP32 hardware acceleration. However, there is a 512-byte limit to the size of the variables used in an exponential modulo calculation. One of the steps in the SRP code used a 768-byte variable, which cannot be handled in version 2.0.0 though it works fine in version 1.0.6. Solution was to simply reduce the 768-byte variable by modulo N prior to performing the exponential modulo calculation.
Simplified enableAutoStartAP() so it no longer takes any arguments. It now simply enables the auto launch of the WiFi Access Point at start-up if WiFi Credentials are not found.
New method setApFunction() will now be used to set an alternative method for the WiFi Access Point. This will be called anytime 'A' is typed into the CLI, which also covers the auto-launch of the AP at start-up a well as starting it via the Control Button, since both of these functions call processCommand('A').
To enable save/restore for a Characteristic, set second parameter to TRUE when instantiating. Since first parameter was optional as well, this requires setting it as well.
Next up: Must add logic to setVal() to store new value as well.
Allows the user to add a command function to the Command Line Interface. All User Commands are defined with a '@' prefix.
To Do: Document this new feature.
New SpanService method addLink(SpanService *svc), where svc is a pointer to the SpanService that is being specified as a Linked Service for the current Service.
addLink() returns a pointer to "this" so may be chained
homeSpan.enableOTA() is now homeSpan.enableOTA(boolean auth=true). Set auth=false to disable password authentication. Set to true, or leave blank, to enable password authentication.
homeSpan.begin() automatically resizes maxConnections to ensure it is at or below maxLimit, where maxLimit=CONFIG_LWIP_MAX_SOCKETS-2-otaEnabled.
maxConnections still defaults to 8 if unspecified, which means it is reduced to 7 if OTA is enabled. Users should set maxConnections to a lower number is they have implemented other socket-based services in their sketch
HomeSpan will call a user-defined function upon establishing WiFi connectivity.
Set function with homeSpan.setWifiCallback(f), where f must be of form void f().
Specify with homeSpan.setSketchVersion(char *).
Read back with homeSpan.getSketchVersion().
Also, MDNS now broadcasts three new fields:
hspn = HomeSpan Version
sketch = Sketch Version
ota = "yes" if OTA enabled, else "no"
These are all optional to HAP but useful if trying to keep track of version updates when using OTA and Serial Monitor is not available.
A 16-byte SALT with a leading zero would be sent as only a 15-byte number. The chance of this occuring is 1 in 256, which is small but still significant. Solution is to specify required size of MPI output in loadTLV. This forces mbedtls_mpi_write_binary() to pad with leading zeros.
Also eliminated unused code (TLV pack_old).
Setup ID can now be stored in NVS and set dynamically with the 'Q' command. However, homeSpan.setQRID(char *id) will override if present, but will not change the default stored in the NVS. This default wil be used once again if homeSpan.setQRID() is removed from the sektch.
If the NVS is empty, the default is set to "HSPN" as in version 1.1.4.