Build versioning, HTTP API, disable SSL for now, indent cleanup
parent
e5629c9b04
commit
8e8070e7b6
|
@ -33,3 +33,10 @@ Oh my, that's slow.^W^Wquite fast, when patched properly.
|
||||||
**WARNING!** `Sming.reset();` jumps to (serial) bootloader right after flashing.
|
**WARNING!** `Sming.reset();` jumps to (serial) bootloader right after flashing.
|
||||||
This causes OTA to fail with `wdt reset`. External RESET assert is required after
|
This causes OTA to fail with `wdt reset`. External RESET assert is required after
|
||||||
flashing.
|
flashing.
|
||||||
|
|
||||||
|
TODO
|
||||||
|
----
|
||||||
|
* Refactor endpoint handling
|
||||||
|
* Fix mDNS
|
||||||
|
* Store configuration (credentials, broker IP, maybe endpoints?) in
|
||||||
|
flash memory
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
|
|
||||||
#define TOPIC_PREFIX "iot/"
|
#define TOPIC_PREFIX "iot/"
|
||||||
|
|
||||||
#define OTA_URL "http://" MQTT_BROKER "/"
|
#define OTA_URL "http://" MQTT_BROKER "/api/1/ota/"
|
||||||
|
|
||||||
#define BTN_PIN 0
|
#define BTN_PIN 0
|
||||||
#define LED_PIN 2
|
#define LED_PIN 2
|
||||||
|
|
|
@ -1,16 +1,17 @@
|
||||||
#include <SpejsNode.h>
|
#include <SpejsNode.h>
|
||||||
|
#include <ver.h>
|
||||||
|
|
||||||
void SpejsNode::init() {
|
void SpejsNode::init() {
|
||||||
deviceID = WifiStation.getMAC().substring(6, 12);
|
deviceID = WifiStation.getMAC().substring(6, 12);
|
||||||
|
|
||||||
currentSlot = 0;
|
currentSlot = 0;
|
||||||
if(!rboot_get_last_boot_rom(¤tSlot)) {
|
if(!rboot_get_last_boot_rom(¤tSlot)) {
|
||||||
currentSlot = rboot_get_current_rom();
|
currentSlot = rboot_get_current_rom();
|
||||||
}
|
}
|
||||||
|
|
||||||
Serial.begin(115200);
|
Serial.begin(115200);
|
||||||
Serial.systemDebugOutput(false); // Debug output to serial
|
Serial.systemDebugOutput(false); // Debug output to serial
|
||||||
Serial.print("*** SpejsNode init, running on:");
|
Serial.print("*** SpejsNode init, running on: ");
|
||||||
Serial.print(deviceID);
|
Serial.print(deviceID);
|
||||||
Serial.printf(", current rom: %d\r\n", currentSlot);
|
Serial.printf(", current rom: %d\r\n", currentSlot);
|
||||||
|
|
||||||
|
@ -20,10 +21,10 @@ void SpejsNode::init() {
|
||||||
WifiAccessPoint.enable(false);
|
WifiAccessPoint.enable(false);
|
||||||
|
|
||||||
WifiStation.waitConnection(
|
WifiStation.waitConnection(
|
||||||
ConnectionDelegate(&SpejsNode::onConnected, this),
|
ConnectionDelegate(&SpejsNode::onConnected, this),
|
||||||
20, *[] {
|
20, *[] {
|
||||||
Serial.println("Connection failed");
|
Serial.println("Connection failed");
|
||||||
});
|
});
|
||||||
|
|
||||||
inputs["control"] = MqttStringSubscriptionCallback(&SpejsNode::controlHandler, this);
|
inputs["control"] = MqttStringSubscriptionCallback(&SpejsNode::controlHandler, this);
|
||||||
}
|
}
|
||||||
|
@ -31,19 +32,69 @@ void SpejsNode::init() {
|
||||||
void SpejsNode::keepAliveHandler() {
|
void SpejsNode::keepAliveHandler() {
|
||||||
if(mqtt.getConnectionState() != eTCS_Connected) {
|
if(mqtt.getConnectionState() != eTCS_Connected) {
|
||||||
Serial.println("Reconnecting");
|
Serial.println("Reconnecting");
|
||||||
onConnected();
|
onConnected();
|
||||||
} else {
|
} else {
|
||||||
uint8_t mode;
|
uint8_t mode;
|
||||||
if(rboot_get_last_boot_mode(&mode)) {
|
if(rboot_get_last_boot_mode(&mode)) {
|
||||||
if(mode == MODE_TEMP_ROM) {
|
if(mode == MODE_TEMP_ROM) {
|
||||||
rboot_set_current_rom(currentSlot);
|
rboot_set_current_rom(currentSlot);
|
||||||
Serial.println("Successfuly connected, accepting temp rom");
|
Serial.println("Successfuly connected, accepting temp rom");
|
||||||
} else {
|
} else {
|
||||||
Serial.printf("Not a TEMP ROM boot: %d\r\n", mode);
|
Serial.printf("Not a TEMP ROM boot: %d\r\n", mode);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Serial.println("No boot mode info");
|
Serial.println("No boot mode info");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SpejsNode::httpIndex(HttpRequest &request, HttpResponse &response)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void SpejsNode::httpMetadata(HttpRequest &request, HttpResponse &response)
|
||||||
|
{
|
||||||
|
JsonObjectStream* stream = new JsonObjectStream();
|
||||||
|
JsonObject& json = stream->getRoot();
|
||||||
|
json["version"] = 1;
|
||||||
|
json["device_id"] = deviceID;
|
||||||
|
json["device_type"] = deviceType;
|
||||||
|
json["rom_slot"] = currentSlot;
|
||||||
|
json["rom_rev"] = BUILD_ID;
|
||||||
|
|
||||||
|
JsonArray& endpoints = json.createNestedArray("endpoints");
|
||||||
|
for(unsigned int i = 0; i < inputs.count(); i++) {
|
||||||
|
endpoints.add(inputs.keyAt(i));
|
||||||
|
}
|
||||||
|
response.sendJsonObject(stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SpejsNode::httpFile(HttpRequest &request, HttpResponse &response)
|
||||||
|
{
|
||||||
|
String file = request.getPath();
|
||||||
|
|
||||||
|
if (file[0] == '/')
|
||||||
|
file = file.substring(1);
|
||||||
|
|
||||||
|
if (file.startsWith("api/1/")) {
|
||||||
|
String req = file.substring(6);
|
||||||
|
String key = req.substring(0, req.indexOf("/"));
|
||||||
|
String value = req.substring(req.indexOf("/") + 1);
|
||||||
|
|
||||||
|
if(key.length() == 0 || value.length() == 0 || !inputs.contains(key)) {
|
||||||
|
response.badRequest();
|
||||||
|
} else {
|
||||||
|
inputs[key](key, value);
|
||||||
|
JsonObjectStream* stream = new JsonObjectStream();
|
||||||
|
JsonObject& json = stream->getRoot();
|
||||||
|
json["status"] = (bool)true;
|
||||||
|
response.sendJsonObject(stream);
|
||||||
|
}
|
||||||
|
} else if (file[0] == '.') {
|
||||||
|
response.forbidden();
|
||||||
|
} else {
|
||||||
|
response.setCache(86400, true); // It's important to use cache for better performance.
|
||||||
|
response.sendFile(file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,6 +122,28 @@ void SpejsNode::onConnected() {
|
||||||
mqtt.publish(TOPIC_PREFIX + deviceID + "/type", deviceType);
|
mqtt.publish(TOPIC_PREFIX + deviceID + "/type", deviceType);
|
||||||
|
|
||||||
keepaliveTimer.initializeMs(10000, TimerDelegate(&SpejsNode::keepAliveHandler, this)).start();
|
keepaliveTimer.initializeMs(10000, TimerDelegate(&SpejsNode::keepAliveHandler, this)).start();
|
||||||
|
|
||||||
|
http.listen(80);
|
||||||
|
|
||||||
|
http.addPath("/", HttpPathDelegate(&SpejsNode::httpIndex, this));
|
||||||
|
http.addPath("/metadata.json", HttpPathDelegate(&SpejsNode::httpMetadata, this));
|
||||||
|
|
||||||
|
http.setDefaultHandler(HttpPathDelegate(&SpejsNode::httpFile, this));
|
||||||
|
|
||||||
|
static struct mdns_info info;// *info = (struct mdns_info *)os_zalloc(sizeof(struct mdns_info));
|
||||||
|
char tmp_name[32];
|
||||||
|
("iot-" + deviceID).toCharArray(tmp_name, 32);
|
||||||
|
info.host_name = tmp_name; // You can replace test with your own host name
|
||||||
|
info.ipAddr = WifiStation.getIP();
|
||||||
|
info.server_name = (char *) "spejsiot";
|
||||||
|
info.server_port = 80;
|
||||||
|
info.txt_data[0] = (char *) "version = now";
|
||||||
|
|
||||||
|
char tmp_type[32] = "type = ";
|
||||||
|
deviceType.toCharArray(tmp_type + 7, 32-7);
|
||||||
|
info.txt_data[1] = tmp_type;
|
||||||
|
|
||||||
|
espconn_mdns_init(&info);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SpejsNode::notify(String key, String value) {
|
bool SpejsNode::notify(String key, String value) {
|
||||||
|
@ -144,9 +217,9 @@ void SpejsNode::startOTA() {
|
||||||
#ifndef DISABLE_SPIFFS
|
#ifndef DISABLE_SPIFFS
|
||||||
// use user supplied values (defaults for 4mb flash in makefile)
|
// use user supplied values (defaults for 4mb flash in makefile)
|
||||||
if (slot == 0) {
|
if (slot == 0) {
|
||||||
otaUpdater->addItem(RBOOT_SPIFFS_0, spiffsURL);
|
otaUpdater->addItem(RBOOT_SPIFFS_0, spiffsURL);
|
||||||
} else {
|
} else {
|
||||||
otaUpdater->addItem(RBOOT_SPIFFS_1, spiffsURL);
|
otaUpdater->addItem(RBOOT_SPIFFS_1, spiffsURL);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -158,23 +231,23 @@ void SpejsNode::startOTA() {
|
||||||
|
|
||||||
void SpejsNode::otaUpdateCallback(rBootHttpUpdate& updater, bool result) {
|
void SpejsNode::otaUpdateCallback(rBootHttpUpdate& updater, bool result) {
|
||||||
if(result == true) {
|
if(result == true) {
|
||||||
// success
|
// success
|
||||||
notify("ota", "finished");
|
notify("ota", "finished");
|
||||||
|
|
||||||
uint8 slot;
|
uint8 slot;
|
||||||
|
|
||||||
if (currentSlot == 0)
|
if (currentSlot == 0)
|
||||||
slot = 1;
|
slot = 1;
|
||||||
else
|
else
|
||||||
slot = 0;
|
slot = 0;
|
||||||
|
|
||||||
// set to boot new rom and then reboot
|
// set to boot new rom and then reboot
|
||||||
Serial.printf("Firmware updated, rebooting to rom %d...\r\n", slot);
|
Serial.printf("Firmware updated, rebooting to rom %d...\r\n", slot);
|
||||||
|
|
||||||
rboot_set_temp_rom(slot);
|
rboot_set_temp_rom(slot);
|
||||||
|
|
||||||
System.restart();
|
System.restart();
|
||||||
} else {
|
} else {
|
||||||
notify("ota", "failed");
|
notify("ota", "failed");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@ protected:
|
||||||
String deviceType;
|
String deviceType;
|
||||||
|
|
||||||
MqttClient mqtt;
|
MqttClient mqtt;
|
||||||
|
HttpServer http;
|
||||||
|
|
||||||
Timer keepaliveTimer;
|
Timer keepaliveTimer;
|
||||||
|
|
||||||
|
@ -33,4 +34,7 @@ public:
|
||||||
void mqttCallback(String, String);
|
void mqttCallback(String, String);
|
||||||
void controlHandler(String, String);
|
void controlHandler(String, String);
|
||||||
void otaUpdateCallback(rBootHttpUpdate& updater, bool result);
|
void otaUpdateCallback(rBootHttpUpdate& updater, bool result);
|
||||||
|
void httpFile(HttpRequest &request, HttpResponse &response);
|
||||||
|
void httpIndex(HttpRequest &request, HttpResponse &response);
|
||||||
|
void httpMetadata(HttpRequest &request, HttpResponse &response);
|
||||||
};
|
};
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
extern char* BUILD_ID;
|
|
@ -8,7 +8,7 @@ include ./Makefile-user.mk
|
||||||
# Important parameters check.
|
# Important parameters check.
|
||||||
# We need to make sure SMING_HOME and ESP_HOME variables are set.
|
# We need to make sure SMING_HOME and ESP_HOME variables are set.
|
||||||
# You can use Makefile-user.mk in each project or use enviromental variables to set it globally.
|
# You can use Makefile-user.mk in each project or use enviromental variables to set it globally.
|
||||||
|
|
||||||
ifndef SMING_HOME
|
ifndef SMING_HOME
|
||||||
$(error SMING_HOME is not set. Please configure it in Makefile-user.mk)
|
$(error SMING_HOME is not set. Please configure it in Makefile-user.mk)
|
||||||
endif
|
endif
|
||||||
|
@ -23,7 +23,16 @@ else
|
||||||
include $(SMING_HOME)/Makefile-project.mk
|
include $(SMING_HOME)/Makefile-project.mk
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
$(APP_AR): $(OBJ)
|
||||||
|
$(vecho) "AR $@"
|
||||||
|
|
||||||
|
@echo "char* BUILD_ID = \"$(shell git rev-parse --short HEAD)-$(shell TZ=UTC date +%Y%m%d-%H%M%S)\";" > $(BUILD_BASE)/ver.c
|
||||||
|
cat $(BUILD_BASE)/ver.c
|
||||||
|
$(CC) -c $(BUILD_BASE)/ver.c -o $(BUILD_BASE)/ver.o
|
||||||
|
|
||||||
|
$(Q) $(AR) cru $@ $^ $(BUILD_BASE)/ver.o
|
||||||
|
|
||||||
ota: all
|
ota: all
|
||||||
-mkdir ../master/ota/$(DEVICE) >/dev/null
|
-mkdir ../master/ota/$(DEVICE) >/dev/null
|
||||||
cp -r out/firmware/* ../master/ota/$(DEVICE)
|
cp -r out/firmware/* ../master/ota/$(DEVICE)
|
||||||
python ../master/ota.py $(DEVICE) control ota
|
python ../master/client.py $(DEVICE) control ota
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
MODULES = app ../spejsiot
|
MODULES = app ../spejsiot
|
||||||
DISABLE_SPIFFS = 1
|
DISABLE_SPIFFS = 1
|
||||||
USER_CFLAGS = -I../common
|
USER_CFLAGS = -I../common
|
||||||
ENABLE_SSL = 1
|
ENABLE_SSL = 0
|
||||||
RBOOT_ENABLED = 1
|
RBOOT_ENABLED = 1
|
||||||
RBOOT_BIG_FLASH = 1
|
RBOOT_BIG_FLASH = 1
|
||||||
RBOOT_RTC_ENABLED = 1
|
RBOOT_RTC_ENABLED = 1
|
||||||
|
|
Loading…
Reference in New Issue