#include #include #include #include void SpejsNode::init() { deviceID = WifiStation.getMAC().substring(6, 12); currentSlot = 0; if(!rboot_get_last_boot_rom(¤tSlot)) { currentSlot = rboot_get_current_rom(); } Serial.begin(115200); Serial.systemDebugOutput(false); // Debug output to serial Serial.print("*** SpejsNode init, running on: "); Serial.print(deviceID); Serial.printf(", current rom: %d\r\n", currentSlot); WifiAccessPoint.enable(false); WifiStation.enable(true); WifiStation.config(WIFI_SSID, WIFI_PWD); WifiStation.waitConnection( ConnectionDelegate(&SpejsNode::onConnected, this), 20, *[] { Serial.println("Connection failed"); }); registerEndpoint("$implementation", new ImplementationEndpoint()); // Keepalive Timer initialization keepaliveTimer.initializeMs(10000, TimerDelegate(&SpejsNode::keepAliveHandler, this)).start(); loadJSON(); } //extern int __papiez_pedofil; void SpejsNode::loadJSON() { /* Serial.printf("start: %08x\n", __start_endpoints); Serial.printf("stop: %08x\n", __stop_endpoints); Serial.printf("Endpoints count: %d\n", ENDPOINTS_COUNT); for(int i = 0; i < ENDPOINTS_COUNT; i++) { struct endpoint_def* endpoint = __start_endpoints[i]; Serial.printf(" -> %08x\r\n", endpoint); Serial.printf(" -> name: %s\r\n", endpoint->name); } */ } void SpejsNode::keepAliveHandler() { static int failureCounter = 0; if(!WifiStation.isConnected()) { Serial.println("keepalive: Network reconnect"); if(failureCounter++ < 5) WifiStation.connect(); else System.restart(); } else if(mqtt.getConnectionState() != eTCS_Connected) { Serial.println("keepalive: MQTT reconnect"); if(failureCounter++ < 5) onConnected(); else System.restart(); } else { failureCounter = 0; uint8_t mode; if(rboot_get_last_boot_mode(&mode) && mode == MODE_TEMP_ROM) { rboot_set_current_rom(currentSlot); Serial.println("Successfuly connected, accepting temp rom"); } } } inline String SpejsNode::DEV_TOPIC(String t) { return TOPIC_PREFIX + deviceID + "/" + t; } void SpejsNode::httpIndex(HttpRequest &request, HttpResponse &response) { response.sendString("This is spejsiot device, take a look at: https://wiki.hackerspace.pl/projects:spejsiot\n" "\nDevice type: " + deviceType + "\nFirmware version: " + String(BUILD_ID) + "\nMAC: " + WifiStation.getMAC()); } /* * Successful network connection handler */ void SpejsNode::onConnected() { Serial.println("Connection successful"); // MQTT initialization mqtt.setWill(DEV_TOPIC("$online"), "false", 1, true); #ifdef ENABLE_SSL const uint8_t sha1Fingerprint[] = SSL_FINGERPRINT; mqtt.connect("iot-" + deviceID, "", "", true); mqtt.addSslOptions(SSL_SERVER_VERIFY_LATER); mqtt.setSslFingerprint(sha1Fingerprint, 20); #else mqtt.connect("iot-" + deviceID); #endif for(unsigned int i = 0 ; i < endpoints.count() ; i++) { endpoints.valueAt(i)->onConnected(); } subscribe("$implementation/+"); // Say hello notify("$online", "true"); notify("$homie", "2"); notify("$name", deviceType); notify("$localip", WifiStation.getIP().toString()); notify("$mac", WifiStation.getMAC()); notify("$fw/name", "spejsiot"); notify("$fw/version", BUILD_ID); // HTTP initialization http.listen(80); http.addPath("/", HttpPathDelegate(&SpejsNode::httpIndex, this)); http.setDefaultHandler(HttpPathDelegate(&SpejsNode::httpFile, this)); // mDNS initialization initializeMDNS(); } 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 || !endpoints.contains(key)) { response.badRequest(); } else { EndpointResult result = endpoints[key]->onValue(key, value); JsonObjectStream* stream = new JsonObjectStream(); JsonObject& json = stream->getRoot(); json["status"] = result.status; response.sendJsonObject(stream); } } } void SpejsNode::initializeMDNS() { /* static struct mdns_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; char tmp_version[32] = "version="; int prefix_len = strlen(tmp_version); strncat(tmp_version, BUILD_ID, 32); info->txt_data[0] = tmp_version; char tmp_type[32]; ("type=" + deviceType).toCharArray(tmp_type, 32); info->txt_data[1] = tmp_type; espconn_mdns_init(info); */ } /* * Publish on device-specific topic */ bool SpejsNode::notify(String key, String value) { mqtt.publish(DEV_TOPIC(key), value, true); return mqtt.getConnectionState() == eTCS_Connected; } /* * Subsribe to device-specific topic */ bool SpejsNode::subscribe(String topic) { mqtt.subscribe(DEV_TOPIC(topic)); return mqtt.getConnectionState() == eTCS_Connected; } /* * Register new endpoint */ void SpejsNode::registerEndpoint(String key, Endpoint* endpoint) { endpoints[key] = endpoint; endpoint->bind(key, this); } void SpejsNode::mqttCallback(String origtopic, String value) { /*int propPos = origtopic.indexOf("/", devicePrefix.length()); String endpoint = origtopic.substring(devicePrefix.length(), propPos); String property = origtopic.substring(propPos+1, origtopic.indexOf("/", propPos+1)); if(endpoints.contains(endpoint)) { Serial.printf("%s - %s response: %d\n", endpoint.c_str(), property.c_str(), endpoints[endpoint]->onValue(property, value).status); } else { Serial.println("unknown topic? " + endpoint); }*/ for(unsigned int i = 0 ; i < endpoints.count() ; i++) { endpoints.valueAt(i)->onMessage(origtopic, value); } }