diff --git a/README.md b/README.md index 5a0f819509..2676f91342 100644 --- a/README.md +++ b/README.md @@ -68,7 +68,7 @@ Please note Version 4 documentation is at [sming.readthedocs.io](https://sming.r * With clients supporting: HTTP, MQTT, WebSockets and SMTP. * And servers for: DNS, FTP, HTTP(+ WebSockets), Telnet. * With [SSL support](https://sming.readthedocs.io/en/latest/_inc/Sming/Components/ssl/index.html) for all network clients and servers. Based on [axTLS](http://axtls.sourceforge.net/) and [BearSSL](https://www.bearssl.org/). - * Out of the box support for OTA over HTTPS. + * Over-The-Air(OTA) firmware upgrades via HTTP(S) and MQTT(S). * ESP8266 specific features. * Integrated boot loader [rboot](https://sming.readthedocs.io/en/latest/_inc/Sming/Components/rboot/index.html) with support for 1MB ROMs, OTA firmware updating and ROM switching. * [Crash handlers](https://sming.readthedocs.io/en/latest/information/debugging.html) for analyzing/handling system restarts due to fatal errors or WDT resets. diff --git a/Sming/Arch/Host/Components/hostlib/startup.cpp b/Sming/Arch/Host/Components/hostlib/startup.cpp index 7b09ea3797..6349932a03 100644 --- a/Sming/Arch/Host/Components/hostlib/startup.cpp +++ b/Sming/Arch/Host/Components/hostlib/startup.cpp @@ -241,7 +241,7 @@ int main(int argc, char* argv[]) } if(config.pause != 0) { - hostmsg("If required, you may start terminal application(s) now"); + host_debug_i("If required, you may start terminal application(s) now"); pause(config.pause); } diff --git a/Sming/Arch/Host/spiffs-two-roms.hw b/Sming/Arch/Host/spiffs-two-roms.hw new file mode 100644 index 0000000000..80128f0191 --- /dev/null +++ b/Sming/Arch/Host/spiffs-two-roms.hw @@ -0,0 +1,13 @@ +{ + "name": "Two ROM slots with single SPIFFS", + "base_config": "spiffs", + "partitions": { + "rom1": { + "address": "0x108000", + "size": "992K", + "type": "app", + "subtype": "ota_1", + "filename": "$(BLANK_BIN)" + } + } +} diff --git a/Sming/Libraries/OtaUpgradeMqtt/.cs b/Sming/Libraries/OtaUpgradeMqtt/.cs new file mode 100644 index 0000000000..e69de29bb2 diff --git a/Sming/Libraries/OtaUpgradeMqtt/README.rst b/Sming/Libraries/OtaUpgradeMqtt/README.rst new file mode 100644 index 0000000000..55386d1f0a --- /dev/null +++ b/Sming/Libraries/OtaUpgradeMqtt/README.rst @@ -0,0 +1,155 @@ +OTA Firmware Upgrade via MQTT +============================= + +.. highlight:: c++ + +Introduction +------------ + +This library allows Sming applications to upgrade their firmware Over-The-Air (OTA) using the MQTT protocol. +MTQTT has less overhead compared to HTTP and can be used for faster delivery of application updates. + +Using +----- + +1. Add ``COMPONENT_DEPENDS += OtaUpgradeMqtt`` to your application componenent.mk file. +2. Add these lines to your application:: + + #include + + #if ENABLE_OTA_ADVANCED + #include + #endif + + MqttClient mqtt; + + // Call when IP address has been obtained + void onIp(IpAddress ip, IpAddress mask, IpAddress gateway) + { + // ... + + mqtt.connect(Url(MQTT_URL), "sming"); + + #if ENABLE_OTA_ADVANCED + /* + * The advanced parser suppors all firmware upgrades supported by the `OtaUpgrade` library. + * `OtaUpgrade` library provides firmware signing, firmware encryption and so on. + */ + auto parser = new OtaUpgrade::Mqtt::AdvancedPayloadParser(APP_VERSION_PATCH); + #else + /* + * The command below uses class that stores the firmware directly + * using RbootOutputStream on a location provided by us + */ + auto parser = new OtaUpgrade::Mqtt::RbootPayloadParser(part, APP_VERSION_PATCH); + #endif + + mqtt.setPayloadParser([parser] + (MqttPayloadParserState& state, mqtt_message_t* message, const char* buffer, int length) -> int + { + return parser->parse(state, message, buffer, length); + }); + + String updateTopic = "a/test/u/4.3"; + mqtt.subscribe(updateTopic); + + // ... + } + +See the :sample:`Upgrade` sample application. + +Versioning Principles +--------------------- +To simplify the OTA process we strongly recommend the following versioning principles for your application: + +1. Use `semantic versioning `_. + If your current application version is 4.3.1 then 4 is the major, 3 is the minor and 1 is the patch version number. + +2. Every application firmware knows its version. + +3. An application with the same major and minor version should be compatible for update no matter what the patch number is. + If the new firmware is not compatible then a new minor or major version should be used. + +Theory Of Operation +------------------- +1. On a period of time the application connects to check if there is a new version of the firmware. + In your application this period has to be carefully selected so that OTA updates occur when the device has + enough resources: memory, space on flash, power and time to complete such an update. Also there should be no critical task running at the moment. + Depending on the size of the new firmware and the speed of the connection an update can take 10 to 20 seconds. + +2. The application connects via MQTT to a remote server and subscribes to a special topic. The topic is based on the + application id and its current version. If the current application id is ``test`` and version is ``4.3.1`` then the topic that will be used for OTA is ``a/test/u/4.3``. + +3. If there is a need to support both stable and unstable/nightly builds then the topic name can have `s` or `u` suffix. For example + all stable versions should be published and downloaded from the topic ``a/test/u/4.3/s``. For the unstable ones we can use the topic ``a/test/u/4.3/u``. + If an application is interested in both stable and unstable versions then it can subscribe using the following pattern ``a/test/u/4.3/+``. + +4. The application is waiting for new firmware. When the application is on battery than it makes sense to wait for a limited time and if there is no + message coming back to disconnect. + +Firmware packaging +------------------ +The firmware update must come as one MQTT message. The MQTT protocol allows messages with a maximum size of 268435455 bytes approx 260MB. +This should be perfectly enough for a device that has maximum 1MB available for an application ROM. + +One MQTT message contains: + +- patch version of the firmware +- followed by the firmware data itself + +Based on the :envvar:`ENABLE_OTA_VARINT_VERSION` the patch version can be encoded either using one byte or a `varint `_. +Based on :envvar:`ENABLE_OTA_ADVANCED` the firmware data can be either without any encoding or be signed and encrypted. + +To simplify the packaging this library comes with a tool called ``deployer``. To create a package type the following from your application:: + + make ota-pack OTA_PATCH_VERSION=127 + +Replace 127 with the desired patch version. +If the option ``OTA_PATCH_VERSION`` is omitted from the command line then the patch version will be generated automatically and it will contain the current unix timestamp. + +Once a package is created it can be deployed to the firmware MQTT server using the command below:: + + make ota-deploy MQTT_FIRMWARE_URL=mqtt://relser:relpassword@attachix.com/a/test/u/4.3 + +The ``MQTT_FIRMWARE_URL`` above specifies that + +- protocol is: mqtt without SSL. Allowed values here are ``mqtt`` and ``mqtts``. The latter uses SSL. +- user is: relser +- password is: relpassword +- host is: attachix.com +- path is: /a/test/u/4.3. The path without leading and ending slashes is used to generate the topic name ``a/test/u/4.3``. + +Make sure to replace the MQTT_FIRMWARE_URL value with your MQTT server credentials, host and topic. + +Security +-------- +For additional security a standard SSL/TLS can be used + +1. The communication should be secured using standard SSL. + +2. To prove that the server is the correct one: The MQTT clients should pin the public key fingerprint on the server. + OR have a list of public key fingerprints that are allowed. + +3. To prove that the clients are allowed to connect: Every MQTT client should also have a client certificate that is signed by the server. + +Configuration +------------- + +.. envvar:: ENABLE_OTA_VARINT_VERSION + + Default: 1 (enabled) + + If set to 1 the OTA upgrade mechanism and application will use a `varint `_ + encoding for the patch version. Thus allowing unlimited number of patch versions. Useful for enumerating unstable/nightly releases. + A bit more difficult to read and write but allows for unlimited versions. + + If set to 0 the OTA upgrade mechanism and application will use one byte for the patch version which will limit it to 256 possible patch versions. + Useful for enumarating stable releases. Easier to write and read but limited to 256 versions only. + +.. envvar:: ENABLE_OTA_ADVANCED + + Default: 0 (disabled) + + If set to 1 the library will work with OtaUpgradeStream which supports signature and encryption of the firmware data itself. + See :component:`OtaUpgrade` for details. In the application the AdvancedPayloadParser can be used to do the MQTT message handling. + diff --git a/Sming/Libraries/OtaUpgradeMqtt/api.rst b/Sming/Libraries/OtaUpgradeMqtt/api.rst new file mode 100644 index 0000000000..e9aca95651 --- /dev/null +++ b/Sming/Libraries/OtaUpgradeMqtt/api.rst @@ -0,0 +1,8 @@ +OTA Upgrade over MQTT classes +============================= + +.. doxygentypedef:: OtaUpgrade::Mqtt + +.. doxygenclass:: OtaUpgrade::Mqtt::PayloadParser +.. doxygenclass:: OtaUpgrade::Mqtt::RbootPayloadParser +.. doxygenclass:: OtaUpgrade::Mqtt::AdvancedPayloadParser diff --git a/Sming/Libraries/OtaUpgradeMqtt/component.mk b/Sming/Libraries/OtaUpgradeMqtt/component.mk new file mode 100644 index 0000000000..7896ab0797 --- /dev/null +++ b/Sming/Libraries/OtaUpgradeMqtt/component.mk @@ -0,0 +1,49 @@ +COMPONENT_SRCDIRS := +COMPONENT_SRCFILES := src/PayloadParser.cpp src/RbootPayloadParser.cpp +COMPONENT_INCDIRS := src/include + +# If enabled (set to 1) then we can use all sofisticated mechanisms to upgrade the firmware using the ``OtaUpgrade`` library. +COMPONENT_VARS := ENABLE_OTA_ADVANCED +ENABLE_OTA_ADVANCED ?= 0 + +ifneq ($(ENABLE_OTA_ADVANCED),0) + COMPONENT_SRCFILES += src/AdvancedPayloadParser.cpp + COMPONENT_DEPENDS := OtaUpgrade +endif + +# If enabled (set to 1) then we can use unlimited number of patch versions +COMPONENT_VARS += ENABLE_OTA_VARINT_VERSION +ENABLE_OTA_VARINT_VERSION ?= 1 + +COMPONENT_CXXFLAGS := -DENABLE_OTA_ADVANCED=$(ENABLE_OTA_ADVANCED) \ + -DENABLE_OTA_VARINT_VERSION=$(ENABLE_OTA_VARINT_VERSION) + +##@Firmware Upgrade + +OTA_TOOLS := $(COMPONENT_PATH)/tools +OTA_DEPLOYMENT_TOOL = $(OTA_TOOLS)/deployer/out/Host/debug/firmware/deployer$(TOOL_EXT) + +$(OTA_DEPLOYMENT_TOOL): + $(Q) $(MAKE) -C $(OTA_TOOLS)/deployer SMING_ARCH=Host ENABLE_CUSTOM_LWIP=2 + + +# SDP = Sming Deployment Pakage +OTA_PACKAGE_EXT =.sdp + +OTA_PATCH_VERSION ?= $(shell date +%s) + +PACKAGE_IN = $(RBOOT_ROM_0_BIN) +ifneq ($(ENABLE_OTA_ADVANCED), 0) + PACKAGE_IN = $(OTA_UPGRADE_FILE) +endif +PACKAGE_OUT = $(PACKAGE_IN)$(OTA_PACKAGE_EXT) + +.PHONY: ota-pack +ota-pack: $(PACKAGE_OUT) ##Creates a deployment package from the current application (use OTA_PATCH_VERSION to specify the version number) + +$(PACKAGE_OUT): $(PACKAGE_IN) $(OTA_DEPLOYMENT_TOOL) + $(Q) $(OTA_DEPLOYMENT_TOOL) pack --debug=0 --nonet -- $(PACKAGE_IN) $(PACKAGE_OUT) $(OTA_PATCH_VERSION) $(ENABLE_OTA_VARINT_VERSION) + +.PHONY: ota-deploy +ota-deploy: $(PACKAGE_OUT) ##Uploads new firmware version of the current application (use MQTT_FIRMWARE_URL to specify the MQTT URL) + $(Q) $(OTA_DEPLOYMENT_TOOL) deploy --debug=0 -- $(PACKAGE_OUT) $(MQTT_FIRMWARE_URL) diff --git a/Sming/Libraries/OtaUpgradeMqtt/samples/Upgrade/.cproject b/Sming/Libraries/OtaUpgradeMqtt/samples/Upgrade/.cproject new file mode 100644 index 0000000000..e1450b6031 --- /dev/null +++ b/Sming/Libraries/OtaUpgradeMqtt/samples/Upgrade/.cproject @@ -0,0 +1,151 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + make + -f ${ProjDirPath}/Makefile + all + true + true + true + + + make + -f ${ProjDirPath}/Makefile + clean + true + true + true + + + make + -f ${ProjDirPath}/Makefile + flash + true + true + true + + + make + -f ${ProjDirPath}/Makefile + flashonefile + true + true + true + + + make + -f ${ProjDirPath}/Makefile + flashinit + true + true + true + + + make + -f ${ProjDirPath}/Makefile + flashboot + true + true + true + + + make + -f ${ProjDirPath}/Makefile + rebuild + true + true + true + + + + + + + + + + + + + + + + + + + + diff --git a/Sming/Libraries/OtaUpgradeMqtt/samples/Upgrade/.cs b/Sming/Libraries/OtaUpgradeMqtt/samples/Upgrade/.cs new file mode 100644 index 0000000000..e69de29bb2 diff --git a/Sming/Libraries/OtaUpgradeMqtt/samples/Upgrade/.gitignore b/Sming/Libraries/OtaUpgradeMqtt/samples/Upgrade/.gitignore new file mode 100644 index 0000000000..a662abf847 --- /dev/null +++ b/Sming/Libraries/OtaUpgradeMqtt/samples/Upgrade/.gitignore @@ -0,0 +1 @@ +ota.key diff --git a/Sming/Libraries/OtaUpgradeMqtt/samples/Upgrade/.project b/Sming/Libraries/OtaUpgradeMqtt/samples/Upgrade/.project new file mode 100644 index 0000000000..76f0847014 --- /dev/null +++ b/Sming/Libraries/OtaUpgradeMqtt/samples/Upgrade/.project @@ -0,0 +1,28 @@ + + + Ota_Mqtt + + + SmingFramework + + + + org.eclipse.cdt.managedbuilder.core.genmakebuilder + clean,full,incremental, + + + + + org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder + full,incremental, + + + + + + org.eclipse.cdt.core.cnature + org.eclipse.cdt.core.ccnature + org.eclipse.cdt.managedbuilder.core.managedBuildNature + org.eclipse.cdt.managedbuilder.core.ScannerConfigNature + + diff --git a/Sming/Libraries/OtaUpgradeMqtt/samples/Upgrade/Makefile b/Sming/Libraries/OtaUpgradeMqtt/samples/Upgrade/Makefile new file mode 100644 index 0000000000..ff51b6c3a7 --- /dev/null +++ b/Sming/Libraries/OtaUpgradeMqtt/samples/Upgrade/Makefile @@ -0,0 +1,9 @@ +##################################################################### +#### Please don't change this file. Use component.mk instead #### +##################################################################### + +ifndef SMING_HOME +$(error SMING_HOME is not set: please configure it as an environment variable) +endif + +include $(SMING_HOME)/project.mk diff --git a/Sming/Libraries/OtaUpgradeMqtt/samples/Upgrade/README.rst b/Sming/Libraries/OtaUpgradeMqtt/samples/Upgrade/README.rst new file mode 100644 index 0000000000..cc14bab324 --- /dev/null +++ b/Sming/Libraries/OtaUpgradeMqtt/samples/Upgrade/README.rst @@ -0,0 +1,88 @@ +OTA over MQTT +============= + +.. highlight:: bash + +Introduction +------------ + +This example demonstrates how you can create an application that updates its firmware Over The Air (OTA) using the MQTT protocol. +This application uses :component:`OtaUpgradeMqtt` and follows the recommended versioning principles. + +Based on :envvar:`ENABLE_OTA_ADVANCED` the firmware data can be either without any encoding or be signed and encrypted. + +Tools +----- +There are two tools that facilitate the packiging and deployment of a new firmware. + +For more information read ``Firmware packaging`` in the documentation of the :component:`OtaUpgradeMqtt` component. + +Security +-------- +Depending on :envvar:`ENABLE_SSL` a standard SSL/TLS can be enabled. This way + +1. The communication between the application and the server will be encrypted using standard SSL. + +2. To prove that the server is the correct one: The MQTT clients should pin the public key fingerprint on the server. + OR have a list of public key fingerprints that are allowed. + +3. Depending on :envvar:`ENABLE_CLIENT_CERTIFICATE` the application can send a client certificate that is signed by the server. + +Configuration +------------- + +.. envvar:: APP_ID + + Default: "test" + + This variable contains the unique application name. + +.. envvar:: APP_VERSION + + Default: not set + + Contains the application major and minor versions separated by comma. Example "4.2". + If not set will use the current major and minor version from Sming. + +.. envvar:: APP_VERSION_PATCH + + Default: not set + + Contains the application patch version as integer. For stable versions you can use 0 until 255. + For unstable versions the current timestamp can be used as a patch version. + +.. envvar:: ENABLE_OTA_VARINT_VERSION + + Default: 1 (enabled) + + If set to 1 the OTA upgrade mechanism and application will use a `varint `_ + encoding for the patch version. Thus allowing unlimited number of patch versions. Useful for enumerating unstable/nightly releases. + A bit more difficult to read and write but allows for unlimited versions. + + If set to 0 the OTA upgrade mechanism and application will use one byte for the patch version which will limit it to 256 possible patch versions. + Useful for enumarating stable releases. Easier to write and read but limited to 256 versions only. + +.. envvar:: ENABLE_OTA_ADVANCED + + Default: 0 (disabled) + + If set to 1 the library will work with OtaUpgradeStream which supports signature and encryption of the firmware data itself. + See :component:`OtaUpgrade` for details. + +.. envvar:: ENABLE_SSL + + Default: unset (disable) + + If set to 1 (highly recommended), OTA upgrade files will be trasnferred securely over TLS/SSL. + +.. envvar:: ENABLE_CLIENT_CERTIFICATE + + Default: 0 (disabled) + + Used in combination with ``ENABLE_SSL``. Set to 1 if the remote server requires the application to authenticate via client certficate. + +.. envvar:: MQTT_URL + + Default: depends on ``ENABLE_SSL`` and ``ENABLE_CLIENT_CERTIFICATE`` values + + Url containing the location of the firmware update MQTT server. diff --git a/Sming/Libraries/OtaUpgradeMqtt/samples/Upgrade/app/application.cpp b/Sming/Libraries/OtaUpgradeMqtt/samples/Upgrade/app/application.cpp new file mode 100644 index 0000000000..87dbb20d31 --- /dev/null +++ b/Sming/Libraries/OtaUpgradeMqtt/samples/Upgrade/app/application.cpp @@ -0,0 +1,155 @@ +#include +#include +#include +#include + +#if ENABLE_OTA_ADVANCED +#include +#endif + +// If you want, you can define WiFi settings globally in Eclipse Environment Variables +#ifndef WIFI_SSID +#define WIFI_SSID "PleaseEnterSSID" // Put your SSID and password here +#define WIFI_PWD "PleaseEnterPass" +#endif + +#ifndef APP_VERSION +#include +#define APP_VERSION MACROQUOTE(SMING_MAJOR_VERSION) "." MACROQUOTE(SMING_MINOR_VERSION) +#define APP_VERSION_PATCH SMING_PATCH_VERSION +#endif + +namespace +{ +MqttClient mqtt; + +#if ENABLE_CLIENT_CERTIFICATE +IMPORT_FSTR(privateKeyData, PROJECT_DIR "/files/private.pem.key.der"); +IMPORT_FSTR(certificateData, PROJECT_DIR "/files/certificate.pem.crt.der"); +#endif + +Storage::Partition findRomPartition(uint8_t slot) +{ + auto part = Storage::spiFlash->partitions().findOta(slot); + if(!part) { + debug_w("Rom slot %d not found", slot); + } + return part; +} + +void otaUpdate() +{ + if(mqtt.isProcessing()) { + Serial.println("There is an update in progress. Refusing to start new update."); + return; + } + + uint8 slot = rboot_get_current_rom(); + if(slot == 0) { + slot = 1; + } else { + slot = 0; + } + + Serial.println("Checking for a new application firmware..."); + + auto part = findRomPartition(slot); + if(!part) { + Serial.println("FAILED: Cannot find application address"); + return; + } + +#ifdef ENABLE_SSL + mqtt.setSslInitHandler([](Ssl::Session& session) { + // These fingerprints change very frequently. + static const Ssl::Fingerprint::Cert::Sha1 sha1Fingerprint PROGMEM = {MQTT_FINGERPRINT_SHA1}; + + // Trust certificate only if it matches the SHA1 fingerprint... + session.validators.pin(sha1Fingerprint); + + // We're using fingerprints, so don't attempt to validate full certificate + session.options.verifyLater = true; + +#if ENABLE_CLIENT_CERTIFICATE + session.keyCert.assign(privateKeyData, certificateData); +#endif + + // Use all supported cipher suites to make a connection + session.cipherSuites = &Ssl::CipherSuites::full; + }); +#endif + + mqtt.connect(Url(MQTT_URL), "sming"); + +#if ENABLE_OTA_ADVANCED + /* + * The advanced parser suppors all firmware upgrades supported by the `OtaUpgrade` library. + * `OtaUpgrade` library provides firmware signing, firmware encryption and so on. + */ + auto parser = new OtaUpgrade::Mqtt::AdvancedPayloadParser(APP_VERSION_PATCH); +#else + /* + * The command below uses class that stores the firmware directly + * using RbootOutputStream on a location provided by us + */ + auto parser = new OtaUpgrade::Mqtt::RbootPayloadParser(part, APP_VERSION_PATCH); +#endif + + mqtt.setPayloadParser([parser](MqttPayloadParserState& state, mqtt_message_t* message, const char* buffer, + int length) -> int { return parser->parse(state, message, buffer, length); }); + + String updateTopic = "a/"; + updateTopic += APP_ID; + updateTopic += "/u/"; + updateTopic += APP_VERSION; + debug_d("Subscribing to topic: %s", updateTopic.c_str()); + mqtt.subscribe(updateTopic); +} + +void showInfo() +{ + Serial.printf(_F("\r\nSDK: v%s\r\n"), system_get_sdk_version()); + Serial.printf(_F("Free Heap: %d\r\n"), system_get_free_heap_size()); + Serial.printf(_F("CPU Frequency: %d MHz\r\n"), system_get_cpu_freq()); + Serial.printf(_F("System Chip ID: %x\r\n"), system_get_chip_id()); + + rboot_config conf; + conf = rboot_get_config(); + + debug_d("Count: %d", conf.count); + debug_d("ROM 0: 0x%08x", conf.roms[0]); + debug_d("ROM 1: 0x%08x", conf.roms[1]); + debug_d("ROM 2: 0x%08x", conf.roms[2]); + debug_d("GPIO ROM: %d", conf.gpio_rom); + + Serial.printf(_F("\r\nCurrently running rom %d. Application version: %s\r\n"), conf.current_rom, APP_VERSION); + Serial.println(); +} + +void connectOk(IpAddress ip, IpAddress mask, IpAddress gateway) +{ + /* + This application starts the update right after a successful connecton. + In a real-world application you should start the update procedure + only when the chances of success are high enough. + + For example when there is enough power, free RAM and sufficient time + AND there is no critical task running at the moment. + */ + otaUpdate(); +} + +} // end of anonymous namespace + +void init() +{ + Serial.begin(SERIAL_BAUD_RATE); // 115200 by default + Serial.systemDebugOutput(true); // Debug output to serial + + showInfo(); + + WifiStation.enable(true); + WifiStation.config(WIFI_SSID, WIFI_PWD); + + WifiEvents.onStationGotIP(connectOk); +} diff --git a/Sming/Libraries/OtaUpgradeMqtt/samples/Upgrade/component.mk b/Sming/Libraries/OtaUpgradeMqtt/samples/Upgrade/component.mk new file mode 100644 index 0000000000..806c2b46b6 --- /dev/null +++ b/Sming/Libraries/OtaUpgradeMqtt/samples/Upgrade/component.mk @@ -0,0 +1,62 @@ +## User configurable settings + +## [Application id and version] ## +# Application id +APP_ID ?= "test" + +# Application version: string containing only the major and minor version separated by comma +# APP_VERSION := "1.2" +# Application patch version: integer containing only the patch version +# APP_VERSION_PATCH := 3 + +## [TLS/SSL settings ] ## +# Uncomment the line below to start using SSL +CONFIG_VARS := ENABLE_SSL +# ENABLE_SSL := Bearssl + +# Set this to one if the remote firmware server requires client certificate +# This option is in effect only when ENABLE_SSL is set +CONFIG_VARS += ENABLE_CLIENT_CERTIFICATE +ENABLE_CLIENT_CERTIFICATE ?= 0 + +## [ Firmware Update Server ] ## +CONFIG_VARS += MQTT_URL +ifeq ($(MQTT_URL),) + MQTT_URL := "mqtt://test.mosquitto.org:1883" + ifdef ENABLE_SSL + ifneq ($(ENABLE_CLIENT_CERTIFICATE),0) + MQTT_URL := "mqtts://test.mosquitto.org:8884" + else + MQTT_URL := "mqtts://test.mosquitto.org:8883" + endif + endif +endif + +# This variable contains the SHA1 fingerprint of the SSL certificate of the MQTT server. +# It is used for certificate pinning. Make sure to change it whenever changing the MQTT_URL +CONFIG_VARS += MQTT_FINGERPRINT_SHA1 +MQTT_FINGERPRINT_SHA1 := "0xEE,0xBC,0x4B,0xF8,0x57,0xE3,0xD3,0xE4,0x07,0x54,0x23,0x1E,0xF0,0xC8,0xA1,0x56,0xE0,0xD3,0x1A,0x1C" + +CONFIG_VARS += ENABLE_OTA_ADVANCED +ENABLE_OTA_ADVANCED ?= 0 + +## End of user configurable settings. Don't change anything below this line + +COMPONENT_DEPENDS := OtaUpgradeMqtt + +## use rboot build mode +RBOOT_ENABLED := 1 + +## Use standard hardware config with two ROM slots and two SPIFFS partitions +HWCONFIG := spiffs-two-roms + +APP_CFLAGS = -DMQTT_URL="\"$(MQTT_URL)"\" \ + -DMQTT_FINGERPRINT_SHA1=$(MQTT_FINGERPRINT_SHA1) \ + -DAPP_ID="\"$(APP_ID)"\" \ + -DENABLE_CLIENT_CERTIFICATE=$(ENABLE_CLIENT_CERTIFICATE) \ + -DENABLE_OTA_ADVANCED=$(ENABLE_OTA_ADVANCED) + +ifneq ($(APP_VERSION),) + APP_CFLAGS += -DAPP_VERSION="\"$(APP_VERSION)"\" \ + -DAPP_VERSION_PATCH=$(APP_VERSION_PATCH) +endif \ No newline at end of file diff --git a/Sming/Libraries/OtaUpgradeMqtt/samples/Upgrade/files/certificate.pem.crt.der b/Sming/Libraries/OtaUpgradeMqtt/samples/Upgrade/files/certificate.pem.crt.der new file mode 100644 index 0000000000..05534491e2 Binary files /dev/null and b/Sming/Libraries/OtaUpgradeMqtt/samples/Upgrade/files/certificate.pem.crt.der differ diff --git a/Sming/Libraries/OtaUpgradeMqtt/samples/Upgrade/files/private.pem.key.der b/Sming/Libraries/OtaUpgradeMqtt/samples/Upgrade/files/private.pem.key.der new file mode 100644 index 0000000000..bfd239930f Binary files /dev/null and b/Sming/Libraries/OtaUpgradeMqtt/samples/Upgrade/files/private.pem.key.der differ diff --git a/Sming/Libraries/OtaUpgradeMqtt/src/AdvancedPayloadParser.cpp b/Sming/Libraries/OtaUpgradeMqtt/src/AdvancedPayloadParser.cpp new file mode 100644 index 0000000000..478b9a70d1 --- /dev/null +++ b/Sming/Libraries/OtaUpgradeMqtt/src/AdvancedPayloadParser.cpp @@ -0,0 +1,44 @@ +/**** + * Sming Framework Project - Open Source framework for high efficiency native ESP8266 development. + * Created 2015 by Skurydin Alexey + * http://github.com/SmingHub/Sming + * All files of the Sming Core are provided under the LGPL v3 license. + * + * AdvancedPayloadParser.cpp + * + * Created: 2021 - Slavey Karadzhov + * + ****/ + +#include "include/OtaUpgrade/Mqtt/AdvancedPayloadParser.h" + +namespace OtaUpgrade +{ +namespace Mqtt +{ +bool AdvancedPayloadParser::switchRom(const UpdateState& updateState) +{ + if(updateState.stream == nullptr) { + return false; + } + + auto otaStream = static_cast(updateState.stream); + if(otaStream == nullptr) { + return false; + } + + if(otaStream->hasError()) { + debug_e("Got error: %s", toString(otaStream->errorCode).c_str()); + return false; + } + + return true; +} + +ReadWriteStream* AdvancedPayloadParser::getStorageStream(size_t storageSize) +{ + return new OtaUpgradeStream(); +} + +} // namespace Mqtt +} // namespace OtaUpgrade diff --git a/Sming/Libraries/OtaUpgradeMqtt/src/PayloadParser.cpp b/Sming/Libraries/OtaUpgradeMqtt/src/PayloadParser.cpp new file mode 100644 index 0000000000..b63a479ea5 --- /dev/null +++ b/Sming/Libraries/OtaUpgradeMqtt/src/PayloadParser.cpp @@ -0,0 +1,127 @@ +/**** + * Sming Framework Project - Open Source framework for high efficiency native ESP8266 development. + * Created 2015 by Skurydin Alexey + * http://github.com/SmingHub/Sming + * All files of the Sming Core are provided under the LGPL v3 license. + * + * PayloadParser.cpp + * + * Created: 2021 - Slavey Karadzhov + * + ****/ + +#include "include/OtaUpgrade/Mqtt/PayloadParser.h" + +namespace OtaUpgrade +{ +namespace Mqtt +{ +int PayloadParser::parse(MqttPayloadParserState& state, mqtt_message_t* message, const char* buffer, int length) +{ + if(message == nullptr) { + debug_e("Invalid MQTT message"); + return ERROR_INVALID_MQTT_MESSAGE; + } + + if(length == MQTT_PAYLOAD_PARSER_START) { + UpdateState* updateState = new UpdateState(); + updateState->stream = nullptr; + updateState->started = false; + + state.offset = 0; + state.userData = updateState; + return 0; + } + + auto updateState = static_cast(state.userData); + if(updateState == nullptr) { + debug_e("Update failed for unknown reason!"); + return ERROR_UNKNOWN_REASON; + } + + if(length == MQTT_PAYLOAD_PARSER_END) { + bool skip = (updateState->stream == nullptr); + if(!skip) { + bool success = switchRom(*updateState); + delete updateState->stream; + delete updateState; + if(success) { + debug_d("Switching was successful. Restarting..."); + System.restart(); + } else { + debug_e("Switching failed!"); + } + } + + return 0; + } + + if(buffer == nullptr) { + debug_e("Invalid MQTT message"); + return ERROR_INVALID_MQTT_MESSAGE; + } + + if(!updateState->started) { + size_t offset = 0; + int patchVersion = getPatchVersion(buffer, length, offset, updateState->version); + state.offset += offset; +#if ENABLE_OTA_VARINT_VERSION + if(patchVersion < 0) { + if(state.offset > allowedVersionBytes) { + debug_e("Invalid patch version."); + return ERROR_INVALID_PATCH_VERSION; + } + return 0; + } +#endif + + updateState->started = true; + if(size_t(patchVersion) < currentPatchVersion) { + // The update is not newer than our current patch version + return 0; + } + + length -= offset; + buffer += offset; + + updateState->stream = getStorageStream(message->common.length - offset); + } + + auto stream = updateState->stream; + if(stream == nullptr) { + return 0; + } + + auto written = stream->write(buffer, length); + return (written - length); +} + +int PayloadParser::getPatchVersion(const char* buffer, int length, size_t& offset, size_t versionStart) +{ + if(buffer == nullptr || length < 1) { + return ERROR_INVALID_PATCH_VERSION; + } + + size_t version = versionStart; +#if ENABLE_OTA_VARINT_VERSION + offset = 0; + int useNextByte = 0; + do { + version += (buffer[offset] & 0x7f); + useNextByte = (buffer[offset++] & 0x80); + } while(useNextByte && (offset < size_t(length))); + + if(useNextByte) { + // all the data is consumed and we still don't have a version number?! + return VERSION_NOT_READY; + } +#else + offset = 1; + version += buffer[0]; +#endif + + return version; +} + +} // namespace Mqtt +} // namespace OtaUpgrade diff --git a/Sming/Libraries/OtaUpgradeMqtt/src/RbootPayloadParser.cpp b/Sming/Libraries/OtaUpgradeMqtt/src/RbootPayloadParser.cpp new file mode 100644 index 0000000000..05ca09033d --- /dev/null +++ b/Sming/Libraries/OtaUpgradeMqtt/src/RbootPayloadParser.cpp @@ -0,0 +1,46 @@ +/**** + * Sming Framework Project - Open Source framework for high efficiency native ESP8266 development. + * Created 2015 by Skurydin Alexey + * http://github.com/SmingHub/Sming + * All files of the Sming Core are provided under the LGPL v3 license. + * + * RbootPayloadParser.cpp + * + * Created: 2021 - Slavey Karadzhov + * + ****/ + +#include "include/OtaUpgrade/Mqtt/RbootPayloadParser.h" + +namespace OtaUpgrade +{ +namespace Mqtt +{ +bool RbootPayloadParser::switchRom(const UpdateState& updateState) +{ + uint8_t after; + uint8_t before = rboot_get_current_rom(); + + if(before == 0) { + after = 1; + } else { + after = 0; + } + + debug_d("Swapping from rom %u to rom %u.\r\n", before, after); + + return rboot_set_current_rom(after); +} + +ReadWriteStream* RbootPayloadParser::getStorageStream(size_t storageSize) +{ + if(storageSize > part.size()) { + debug_e("The new rom is too big to fit!"); + return nullptr; + } + + return new RbootOutputStream(part.address(), part.size()); +} + +} // namespace Mqtt +} // namespace OtaUpgrade diff --git a/Sming/Libraries/OtaUpgradeMqtt/src/include/OtaUpgrade/Mqtt/AdvancedPayloadParser.h b/Sming/Libraries/OtaUpgradeMqtt/src/include/OtaUpgrade/Mqtt/AdvancedPayloadParser.h new file mode 100644 index 0000000000..1cf01191cc --- /dev/null +++ b/Sming/Libraries/OtaUpgradeMqtt/src/include/OtaUpgrade/Mqtt/AdvancedPayloadParser.h @@ -0,0 +1,37 @@ +/**** + * Sming Framework Project - Open Source framework for high efficiency native ESP8266 development. + * Created 2015 by Skurydin Alexey + * http://github.com/SmingHub/Sming + * All files of the Sming Core are provided under the LGPL v3 license. + * + * AdvancedPayloadParser.h + * + * Created: 2021 - Slavey Karadzhov + * + ****/ + +#pragma once + +#include "PayloadParser.h" +#include + +namespace OtaUpgrade +{ +namespace Mqtt +{ +/** + * This parser allows the processing of firmware data + * that can be encrypted or have signature + */ +class AdvancedPayloadParser : public PayloadParser +{ +public: + using PayloadParser::PayloadParser; + + bool switchRom(const UpdateState& updateState) override; + + ReadWriteStream* getStorageStream(size_t storageSize) override; +}; + +} // namespace Mqtt +} // namespace OtaUpgrade diff --git a/Sming/Libraries/OtaUpgradeMqtt/src/include/OtaUpgrade/Mqtt/PayloadParser.h b/Sming/Libraries/OtaUpgradeMqtt/src/include/OtaUpgrade/Mqtt/PayloadParser.h new file mode 100644 index 0000000000..41d63dab03 --- /dev/null +++ b/Sming/Libraries/OtaUpgradeMqtt/src/include/OtaUpgrade/Mqtt/PayloadParser.h @@ -0,0 +1,85 @@ +/**** + * Sming Framework Project - Open Source framework for high efficiency native ESP8266 development. + * Created 2015 by Skurydin Alexey + * http://github.com/SmingHub/Sming + * All files of the Sming Core are provided under the LGPL v3 license. + * + * PayloadParser.h + * + * Created: 2021 - Slavey Karadzhov + * + ****/ + +#pragma once + +#include +#include +#include + +namespace OtaUpgrade +{ +namespace Mqtt +{ +constexpr int8_t VERSION_NOT_READY{-1}; + +constexpr int8_t ERROR_INVALID_MQTT_MESSAGE{-1}; +constexpr int8_t ERROR_INVALID_PATCH_VERSION{-2}; +constexpr int8_t ERROR_UNKNOWN_REASON{-10}; + +class PayloadParser +{ +public: + struct UpdateState { + ReadWriteStream* stream{nullptr}; + bool started{false}; + size_t version{0}; + }; + + /** + * @brief + * @param currentPatchVersion + * @param allowedVersionBytes - maximum allowed bytes to be used for describing a patch version + */ + PayloadParser(size_t currentPatchVersion, size_t allowedVersionBytes = 24) + : currentPatchVersion(currentPatchVersion), allowedVersionBytes(allowedVersionBytes) + { + } + + virtual ~PayloadParser() + { + } + + /** + * @brief This method is responsible for switching the rom. + * This method is NOT restarting the system. It will happen lated in the parse method + * @retval true if the switch was successful + */ + virtual bool switchRom(const UpdateState& updateState) = 0; + + /** + * @brief Creates new stream to store the firmware update + * @param size_t storageSize the requested storage size + * + * @retval ReadWriteStream* + */ + virtual ReadWriteStream* getStorageStream(size_t storageSize) = 0; + + /** + * @brief This method takes care to read the incoming MQTT message and pass it to the stream that + * is responsoble for storing the data. + * + * @retval int + * 0 when everything is ok + * <0 when an error has occurred + */ + int parse(MqttPayloadParserState& state, mqtt_message_t* message, const char* buffer, int length); + +private: + int getPatchVersion(const char* buffer, int length, size_t& offset, size_t versionStart = 0); + + size_t currentPatchVersion; + size_t allowedVersionBytes; +}; + +} // namespace Mqtt +} // namespace OtaUpgrade diff --git a/Sming/Libraries/OtaUpgradeMqtt/src/include/OtaUpgrade/Mqtt/RbootPayloadParser.h b/Sming/Libraries/OtaUpgradeMqtt/src/include/OtaUpgrade/Mqtt/RbootPayloadParser.h new file mode 100644 index 0000000000..68e87dd53a --- /dev/null +++ b/Sming/Libraries/OtaUpgradeMqtt/src/include/OtaUpgrade/Mqtt/RbootPayloadParser.h @@ -0,0 +1,43 @@ +/**** + * Sming Framework Project - Open Source framework for high efficiency native ESP8266 development. + * Created 2015 by Skurydin Alexey + * http://github.com/SmingHub/Sming + * All files of the Sming Core are provided under the LGPL v3 license. + * + * RbootPayloadParser.h + * + * Created: 2021 - Slavey Karadzhov + * + ****/ + +#pragma once + +#include "PayloadParser.h" +#include + +namespace OtaUpgrade +{ +namespace Mqtt +{ +/** + * @brief This parser allows the processing of firmware data that is directly stored + * to the flash memory using RbootOutputStream. + */ +class RbootPayloadParser : public PayloadParser +{ +public: + RbootPayloadParser(Storage::Partition part, size_t currentVersion, size_t allowedVersionBytes = 24) + : PayloadParser(currentVersion, allowedVersionBytes), part(part) + { + } + + bool switchRom(const UpdateState& updateState) override; + + ReadWriteStream* getStorageStream(size_t storageSize) override; + +private: + Storage::Partition part; +}; + +} // namespace Mqtt +} // namespace OtaUpgrade diff --git a/Sming/Libraries/OtaUpgradeMqtt/tools/deployer/.cproject b/Sming/Libraries/OtaUpgradeMqtt/tools/deployer/.cproject new file mode 100644 index 0000000000..fecee42f2f --- /dev/null +++ b/Sming/Libraries/OtaUpgradeMqtt/tools/deployer/.cproject @@ -0,0 +1,97 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + make + + all + true + true + true + + + make + + rebuild + true + true + true + + + make + + flash + true + true + true + + + + diff --git a/Sming/Libraries/OtaUpgradeMqtt/tools/deployer/.project b/Sming/Libraries/OtaUpgradeMqtt/tools/deployer/.project new file mode 100644 index 0000000000..0b94d5c588 --- /dev/null +++ b/Sming/Libraries/OtaUpgradeMqtt/tools/deployer/.project @@ -0,0 +1,30 @@ + + + FirmwareDeployer + + + SmingFramework + Libraries + Sming + + + + org.eclipse.cdt.managedbuilder.core.genmakebuilder + clean,full,incremental, + + + + + org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder + full,incremental, + + + + + + org.eclipse.cdt.core.cnature + org.eclipse.cdt.core.ccnature + org.eclipse.cdt.managedbuilder.core.managedBuildNature + org.eclipse.cdt.managedbuilder.core.ScannerConfigNature + + diff --git a/Sming/Libraries/OtaUpgradeMqtt/tools/deployer/Makefile b/Sming/Libraries/OtaUpgradeMqtt/tools/deployer/Makefile new file mode 100644 index 0000000000..ff51b6c3a7 --- /dev/null +++ b/Sming/Libraries/OtaUpgradeMqtt/tools/deployer/Makefile @@ -0,0 +1,9 @@ +##################################################################### +#### Please don't change this file. Use component.mk instead #### +##################################################################### + +ifndef SMING_HOME +$(error SMING_HOME is not set: please configure it as an environment variable) +endif + +include $(SMING_HOME)/project.mk diff --git a/Sming/Libraries/OtaUpgradeMqtt/tools/deployer/README.rst b/Sming/Libraries/OtaUpgradeMqtt/tools/deployer/README.rst new file mode 100644 index 0000000000..5a0f568c0c --- /dev/null +++ b/Sming/Libraries/OtaUpgradeMqtt/tools/deployer/README.rst @@ -0,0 +1,7 @@ +Deployer +======== + +.. highlight:: bash + +Utility to package and deploy firmware files for upgrade over MQTT +See :library:`OtaUpgradeMqtt` for details. diff --git a/Sming/Libraries/OtaUpgradeMqtt/tools/deployer/app/application.cpp b/Sming/Libraries/OtaUpgradeMqtt/tools/deployer/app/application.cpp new file mode 100644 index 0000000000..ae8350511a --- /dev/null +++ b/Sming/Libraries/OtaUpgradeMqtt/tools/deployer/app/application.cpp @@ -0,0 +1,214 @@ +#include +#include + +#ifdef ARCH_HOST +#ifdef __WIN32__ +#include +#endif + +#include +#include +#include +#endif + +// If you want, you can define WiFi settings globally in Eclipse Environment Variables +#ifndef WIFI_SSID +#define WIFI_SSID "PleaseEnterSSID" // Put you SSID and Password here +#define WIFI_PWD "PleaseEnterPass" +#endif + +namespace +{ +MqttClient mqtt; + +#ifdef ARCH_HOST + +size_t charsWriter(const char* buffer, size_t length) +{ + return fwrite(buffer, sizeof(char), length, stdout); +} + +template void print(const T& arg) +{ + String s(arg); + m_nputs(s.c_str(), s.length()); +} + +void println() +{ + m_puts("\r\n"); +} + +template void println(const T& arg) +{ + print(arg); + println(); +} + +int writePatchVersion(int patchVersion, bool useVarInt, ReadWriteStream* output) +{ + if(output == nullptr) { + return -1; + } + + int written = 0; + if(useVarInt) { + while(patchVersion > 0x7f) { + if(output->write(((uint8_t)(patchVersion)) | 0x80) < 0) { + return false; + } + patchVersion >>= 7; + written++; + } + if(output->write(((uint8_t)patchVersion) & 0x7f) < 0) { + return false; + } + written++; + } else { + written = output->write((uint8_t)patchVersion); + } + + return written; +} + +bool pack(const String& inputFileName, const String& outputFileName, size_t patchVersion, bool useVarInt) +{ + HostFileStream input; + input.open(inputFileName); + if(!input.fileExist()) { + m_printf(_F("ERROR: Invalid input file: %s\r\n"), inputFileName.c_str()); + return false; + } + + HostFileStream output; + output.open(outputFileName, eFO_CreateNewAlways | eFO_WriteOnly); + writePatchVersion(patchVersion, useVarInt, &output); + output.copyFrom(&input); + output.close(); + + return true; +} + +bool deploy(const String& outputFileName, const String& url) +{ + if(mqtt.isProcessing()) { + // we are still processing the data... + return false; + } + + HostFileStream* output = new HostFileStream(); + output->open(outputFileName); + if(!output->fileExist()) { + m_printf(_F("ERROR: Invalid input file: %s"), outputFileName.c_str()); + return false; + } + + WifiStation.enable(true, false); + WifiStation.config(WIFI_SSID, WIFI_PWD); + WifiAccessPoint.enable(false, false); + WifiEvents.onStationGotIP([url, output](IpAddress ip, IpAddress netmask, IpAddress gateway) { + Url mqttUrl(url); + + mqtt.connect(mqttUrl, "sming"); + mqtt.setConnectedHandler([mqttUrl, output](MqttClient& client, mqtt_message_t* message) -> int { + if(message == nullptr) { + // invalid message received + return 1; + } + + if(message->connack.return_code) { + m_printf(_F("ERROR: Connection failed. Reason: %s\r\n"), + mqtt_connect_error_string(static_cast(message->connack.return_code))); + System.restart(1000); + return 0; + } + + uint8_t retained = 1; + uint8_t QoS = 2; + uint8_t flags = (uint8_t)(retained + (QoS << 1)); + mqtt.publish(mqttUrl.Path.substring(1), output, flags); + mqtt.setPublishedHandler([](MqttClient& client, mqtt_message_t* message) -> int { + println(F("Firmware uploaded successfully.")); + System.restart(1000); + return 0; + }); + + return 0; + }); + }); + + return true; +} + +void help() +{ + println(); + println(F("Available commands:")); + println(F(" pack fileName.in fileName.out patchVersion Creates a package to be deployed on " + "firmware upgrade server.")); + println(F(" deploy fileName.out mqttUrl Deploys a deployment package to " + "firmware upgrade server.")); + println(); +} + +/* + * Return true to continue execution, false to quit. + */ +bool parseCommands() +{ + auto parameters = commandLine.getParameters(); + if(parameters.count() == 0) { + help(); + return false; + } + + String cmd = parameters[0].text; + if(cmd == "pack") { + if(parameters.count() >= 4) { + bool useVarInt = false; + if(parameters.count() > 4) { + useVarInt = strtol(parameters[4].text, nullptr, 0); + } + if(pack(parameters[1].text, parameters[2].text, strtol(parameters[3].text, nullptr, 0), useVarInt)) { + } + } + + return false; // after packaging the application can be terminated + } + + if(cmd == "deploy") { + if(parameters.count() < 2) { + m_printf(_F("ERROR: Specify package filename.\r\n")); + return false; + } + + if(parameters.count() < 3) { + m_printf(_F("ERROR: Specify MQTT_FIRMWARE_URL.\r\n")); + return false; + } + + return deploy(parameters[1].text, parameters[2].text); + } + + help(); + return false; +} + +#endif // ARCH_HOST + +} // namespace + +void init() +{ + Serial.setTxBufferSize(1024); + Serial.begin(SERIAL_BAUD_RATE); + Serial.systemDebugOutput(true); + +#ifdef ARCH_HOST + m_setPuts(charsWriter); + + if(!parseCommands()) { + System.restart(1000); + } +#endif +} diff --git a/Sming/Libraries/OtaUpgradeMqtt/tools/deployer/component.mk b/Sming/Libraries/OtaUpgradeMqtt/tools/deployer/component.mk new file mode 100644 index 0000000000..fc77dcce33 --- /dev/null +++ b/Sming/Libraries/OtaUpgradeMqtt/tools/deployer/component.mk @@ -0,0 +1,14 @@ +COMPONENT_DEPENDS := OtaUpgradeMqtt +APP_NAME := deployer + +SMING_ARCH := Host + +##@Firmware Upgrade + +APP=$(TARGET_OUT_0) + +pack: application $(APP) ##Pack firmware files for deployment (HOST_PARAMETERS=inputFile packedFile version 1|0. Example: ) + $(Q) $(APP) pack -- $(HOST_PARAMETERS) + +deploy: application $(APP) ##Deploy firmware files to MQTT server (HOST_PARAMETERS=packedFile MQTTQ_URL. Example MQTT user: ) + $(Q) $(APP) deploy -- $(HOST_PARAMETERS) \ No newline at end of file diff --git a/docs/source/getting-started/windows/index.rst b/docs/source/getting-started/windows/index.rst index d9fa84bfaa..b31bd9b026 100644 --- a/docs/source/getting-started/windows/index.rst +++ b/docs/source/getting-started/windows/index.rst @@ -23,6 +23,9 @@ Open an *administrative* **cmd.exe** command prompt and paste the text from the curl -LO https://raw.githubusercontent.com/SmingHub/Sming/develop/Tools/choco-install.cmd && choco-install.cmd +At the moment the Esp32 toolchain is not installed by default. If you want to install it run the following command:: + + choco install -y sming.esp32 .. important:: @@ -32,22 +35,31 @@ Open an *administrative* **cmd.exe** command prompt and paste the text from the It is also inadvisable to continue running with elevated privileges. +If you followed and executed carefully the steps above Sming should be installed and configured. +You can scroll down to :ref:`Build Basic_Blink` to check the installation. + +Optional step: Switch to stable version +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +The installer uses the latest **develop** branch. This one contains great new features and bugfixes but can be ``unstable`` at times. + +Switching to our ``stable`` release will guarantee you that Sming's code will not change so often. +On the downside you will have to wait for all new shiny features and bugfixes. + +If you really want to use the latest ``stable`` release you can type the command below:: -The installer uses the latest **develop** branch. -The command below will get for you the latest ``stable`` release:: + cd %SMING_HOME% + git checkout master + git pull - cd %SMING_HOME% - git checkout master - git pull +Optional step: Re-installation +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ In case something is broken, this will perform a forced re-install of all packages:: rmdir /s /q c:\tools\sming choco install sming -y -f -x - - Packages -------- @@ -107,7 +119,7 @@ To check the installation, open a command prompt and type these commands:: make The project should build without error. - + Next steps ---------- diff --git a/docs/source/index.rst b/docs/source/index.rst index fdb883e3f1..9111286243 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -30,7 +30,7 @@ Summary - And servers for: DNS, FTP, HTTP(+ WebSockets), Telnet. - With :doc:`SSL support <_inc/Sming/Components/ssl/index>` for all network clients and servers. Based on `axTLS `__ and `BearSSL `__. - - Out of the box support for OTA over HTTPS. + - Over-The-Air(OTA) firmware upgrades via HTTP(S) and MQTT(S). - ESP8266 specific features