mirror of
https://github.com/rstrouse/ESPSomfy-RTS.git
synced 2025-12-12 18:42:10 +01:00
parent
82c867d2eb
commit
2feb420551
19 changed files with 163 additions and 461 deletions
2
.github/workflows/release.yaml
vendored
2
.github/workflows/release.yaml
vendored
|
|
@ -7,7 +7,7 @@ on:
|
|||
env:
|
||||
ARDUINO_BOARD_MANAGER_ADDITIONAL_URLS: "https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json"
|
||||
ARDUINO_CLI_VERSION: "0.x"
|
||||
ARDUINO_ESP32_VERSION: "2.0.14"
|
||||
ARDUINO_ESP32_VERSION: "2.0.15"
|
||||
ARDUINO_JSON_VERSION: "6.21.5"
|
||||
ESPTOOL_VERSION: "4.7"
|
||||
LITTLEFS_VERSION: "v2.5.1"
|
||||
|
|
|
|||
|
|
@ -7,10 +7,10 @@
|
|||
|
||||
extern Preferences pref;
|
||||
|
||||
#define SHADE_HDR_VER 22
|
||||
#define SHADE_HDR_VER 23
|
||||
#define SHADE_HDR_SIZE 76
|
||||
#define SHADE_REC_SIZE 276
|
||||
#define GROUP_REC_SIZE 194
|
||||
#define GROUP_REC_SIZE 200
|
||||
#define TRANS_REC_SIZE 74
|
||||
#define ROOM_REC_SIZE 29
|
||||
#define REPEATER_REC_SIZE 77
|
||||
|
|
@ -728,12 +728,14 @@ bool ShadeConfigFile::readGroupRecord(SomfyGroup *group) {
|
|||
this->readString(group->name, sizeof(group->name));
|
||||
group->proto = static_cast<radio_proto>(this->readUInt8(0));
|
||||
group->bitLength = this->readUInt8(56);
|
||||
if(this->header.version >= 23) group->lastRollingCode = this->readUInt16(0);
|
||||
if(group->getRemoteAddress() != 0) {
|
||||
uint16_t rc = pref.getUShort(group->getRemotePrefId(), 0);
|
||||
group->lastRollingCode = max(rc, group->lastRollingCode);
|
||||
if(rc < group->lastRollingCode) pref.putUShort(group->getRemotePrefId(), group->lastRollingCode);
|
||||
}
|
||||
uint8_t lsd = 0;
|
||||
memset(group->linkedShades, 0x00, sizeof(group->linkedShades));
|
||||
for(uint8_t j = 0; j < SOMFY_MAX_GROUPED_SHADES; j++) {
|
||||
uint8_t shadeId = this->readUInt8(0);
|
||||
// Do this to eliminate gaps.
|
||||
|
|
@ -925,6 +927,7 @@ bool ShadeConfigFile::writeGroupRecord(SomfyGroup *group) {
|
|||
this->writeString(group->name, sizeof(group->name));
|
||||
this->writeUInt8(static_cast<uint8_t>(group->proto));
|
||||
this->writeUInt8(group->bitLength);
|
||||
this->writeUInt16(group->lastRollingCode);
|
||||
for(uint8_t j = 0; j < SOMFY_MAX_GROUPED_SHADES; j++) {
|
||||
this->writeUInt8(group->linkedShades[j]);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
#ifndef configsettings_h
|
||||
#define configsettings_h
|
||||
#include "WResp.h"
|
||||
#define FW_VERSION "v2.4.2"
|
||||
#define FW_VERSION "v2.4.3"
|
||||
enum DeviceStatus {
|
||||
DS_OK = 0,
|
||||
DS_ERROR = 1,
|
||||
|
|
@ -161,7 +161,8 @@ enum class conn_types : byte {
|
|||
unset = 0x00,
|
||||
wifi = 0x01,
|
||||
ethernet = 0x02,
|
||||
ethernetpref = 0x03
|
||||
ethernetpref = 0x03,
|
||||
ap = 0x04
|
||||
};
|
||||
class ConfigSettings: BaseSettings {
|
||||
public:
|
||||
|
|
|
|||
60
GitOTA.cpp
60
GitOTA.cpp
|
|
@ -68,20 +68,6 @@ void GitRelease::setAssetProperty(const char *key, const char *val) {
|
|||
}
|
||||
}
|
||||
}
|
||||
bool GitRelease::toJSON(JsonObject &obj) {
|
||||
Timestamp ts;
|
||||
obj["id"] = this->id;
|
||||
obj["name"] = this->name;
|
||||
obj["date"] = ts.getISOTime(this->releaseDate);
|
||||
obj["draft"] = this->draft;
|
||||
obj["preRelease"] = this->preRelease;
|
||||
obj["main"] = this->main;
|
||||
obj["hasFS"] = this->hasFS;
|
||||
obj["hwVersions"] = this->hwVersions;
|
||||
JsonObject ver = obj.createNestedObject("version");
|
||||
this->version.toJSON(ver);
|
||||
return true;
|
||||
}
|
||||
void GitRelease::toJSON(JsonResponse &json) {
|
||||
Timestamp ts;
|
||||
char buff[20];
|
||||
|
|
@ -228,7 +214,7 @@ int16_t GitRepo::getReleases(uint8_t num) {
|
|||
}
|
||||
else {
|
||||
https.end();
|
||||
//sclient.stop();
|
||||
sclient.stop();
|
||||
return httpCode;
|
||||
}
|
||||
}
|
||||
|
|
@ -254,19 +240,6 @@ void GitRepo::toJSON(JsonResponse &json) {
|
|||
}
|
||||
json.endArray();
|
||||
}
|
||||
bool GitRepo::toJSON(JsonObject &obj) {
|
||||
JsonObject fw = obj.createNestedObject("fwVersion");
|
||||
settings.fwVersion.toJSON(fw);
|
||||
JsonObject app = obj.createNestedObject("appVersion");
|
||||
settings.appVersion.toJSON(app);
|
||||
JsonArray arr = obj.createNestedArray("releases");
|
||||
for(uint8_t i = 0; i < GIT_MAX_RELEASES + 1; i++) {
|
||||
if(this->releases[i].id == 0) continue;
|
||||
JsonObject o = arr.createNestedObject();
|
||||
this->releases[i].toJSON(o);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#define UPDATE_ERR_OFFSET 20
|
||||
#define ERR_DOWNLOAD_HTTP -40
|
||||
#define ERR_DOWNLOAD_BUFFER -41
|
||||
|
|
@ -274,11 +247,8 @@ bool GitRepo::toJSON(JsonObject &obj) {
|
|||
|
||||
void GitUpdater::loop() {
|
||||
if(this->status == GIT_STATUS_READY) {
|
||||
//if(this->lastCheck == 0)
|
||||
//this->lastCheck = millis();
|
||||
//else
|
||||
if(settings.checkForUpdate &&
|
||||
//(this->lastCheck + 14400000 < millis() || this->lastCheck == 0) && !rebootDelay.reboot) { // 4 hours
|
||||
(millis() > 60000) && // Wait a minute before checking after boot.
|
||||
(this->lastCheck + 86400000 < millis() || this->lastCheck == 0) && !rebootDelay.reboot) { // 1 day
|
||||
this->checkForUpdate();
|
||||
}
|
||||
|
|
@ -302,6 +272,7 @@ void GitUpdater::loop() {
|
|||
void GitUpdater::checkForUpdate() {
|
||||
if(this->status != 0) return; // If we are already checking.
|
||||
Serial.println("Check github for updates...");
|
||||
|
||||
this->status = GIT_STATUS_CHECK;
|
||||
settings.printAvailHeap();
|
||||
this->lastCheck = millis();
|
||||
|
|
@ -349,21 +320,6 @@ void GitUpdater::toJSON(JsonResponse &json) {
|
|||
this->latest.toJSON(json);
|
||||
json.endObject();
|
||||
}
|
||||
|
||||
void GitUpdater::toJSON(JsonObject &obj) {
|
||||
obj["available"] = this->updateAvailable;
|
||||
obj["status"] = this->status;
|
||||
obj["error"] = this->error;
|
||||
obj["cancelled"] = this->cancelled;
|
||||
obj["checkForUpdate"] = settings.checkForUpdate;
|
||||
obj["inetAvailable"] = this->inetAvailable;
|
||||
JsonObject fw = obj.createNestedObject("fwVersion");
|
||||
settings.fwVersion.toJSON(fw);
|
||||
JsonObject app = obj.createNestedObject("appVersion");
|
||||
settings.appVersion.toJSON(app);
|
||||
JsonObject latest = obj.createNestedObject("latest");
|
||||
this->latest.toJSON(latest);
|
||||
}
|
||||
void GitUpdater::emitUpdateCheck(uint8_t num) {
|
||||
JsonSockEvent *json = sockEmit.beginEmit("fwStatus");
|
||||
json->beginObject();
|
||||
|
|
@ -384,16 +340,6 @@ void GitUpdater::emitUpdateCheck(uint8_t num) {
|
|||
json->endObject();
|
||||
json->endObject();
|
||||
sockEmit.endEmit(num);
|
||||
/*
|
||||
ClientSocketEvent evt("fwStatus");
|
||||
DynamicJsonDocument doc(512);
|
||||
JsonObject obj = doc.to<JsonObject>();
|
||||
this->toJSON(obj);
|
||||
if(num == 255)
|
||||
sockEmit.sendToClients("fwStatus", doc);
|
||||
else
|
||||
sockEmit.sendToClient(num, "fwStatus", doc);
|
||||
*/
|
||||
}
|
||||
int GitUpdater::checkInternet() {
|
||||
int err = 500;
|
||||
|
|
|
|||
3
GitOTA.h
3
GitOTA.h
|
|
@ -28,14 +28,12 @@ class GitRelease {
|
|||
appver_t version;
|
||||
void setReleaseProperty(const char *key, const char *val);
|
||||
void setAssetProperty(const char *key, const char *val);
|
||||
bool toJSON(JsonObject &obj);
|
||||
void toJSON(JsonResponse &json);
|
||||
};
|
||||
class GitRepo {
|
||||
public:
|
||||
int16_t getReleases(uint8_t num = GIT_MAX_RELEASES);
|
||||
GitRelease releases[GIT_MAX_RELEASES + 1];
|
||||
bool toJSON(JsonObject &obj);
|
||||
void toJSON(JsonResponse &json);
|
||||
};
|
||||
class GitUpdater {
|
||||
|
|
@ -60,7 +58,6 @@ class GitUpdater {
|
|||
void setFirmwareFile();
|
||||
void setCurrentRelease(GitRepo &repo);
|
||||
void loop();
|
||||
void toJSON(JsonObject &obj);
|
||||
void toJSON(JsonResponse &json);
|
||||
bool recoverFilesystem();
|
||||
int checkInternet();
|
||||
|
|
|
|||
12
MQTT.cpp
12
MQTT.cpp
|
|
@ -299,18 +299,6 @@ bool MQTTClass::publish(const char *topic, uint32_t val, bool retain) {
|
|||
snprintf(g_content, sizeof(g_content), "%u", val);
|
||||
return this->publish(topic, g_content, retain);
|
||||
}
|
||||
bool MQTTClass::publish(const char *topic, JsonDocument &doc, bool retain) {
|
||||
serializeJson(doc, g_content, sizeof(g_content));
|
||||
return this->publish(topic, g_content, retain);
|
||||
}
|
||||
bool MQTTClass::publish(const char *topic, JsonArray &arr, bool retain) {
|
||||
serializeJson(arr, g_content, sizeof(g_content));
|
||||
return this->publish(topic, g_content, retain);
|
||||
}
|
||||
bool MQTTClass::publish(const char *topic, JsonObject &obj, bool retain) {
|
||||
serializeJson(obj, g_content, sizeof(g_content));
|
||||
return this->publish(topic, g_content, retain);
|
||||
}
|
||||
bool MQTTClass::unpublish(const char *topic) {
|
||||
if(mqttClient.connected()) {
|
||||
char top[128];
|
||||
|
|
|
|||
3
MQTT.h
3
MQTT.h
|
|
@ -17,9 +17,6 @@ class MQTTClass {
|
|||
void reset();
|
||||
bool unpublish(const char *topic);
|
||||
bool publish(const char *topic, const char *payload, bool retain = false);
|
||||
bool publish(const char *topic, JsonDocument &doc, bool retain = false);
|
||||
bool publish(const char *topic, JsonArray &arr, bool retain = false);
|
||||
bool publish(const char *topic, JsonObject &obj, bool retain = false);
|
||||
bool publish(const char *topic, uint8_t val, bool retain = false);
|
||||
bool publish(const char *topic, int8_t val, bool retain = false);
|
||||
bool publish(const char *topic, uint32_t val, bool retain = false);
|
||||
|
|
|
|||
224
Network.cpp
224
Network.cpp
|
|
@ -15,6 +15,8 @@ extern SocketEmitter sockEmit;
|
|||
extern MQTTClass mqtt;
|
||||
extern rebootDelay_t rebootDelay;
|
||||
extern Network net;
|
||||
extern SomfyShadeController somfy;
|
||||
|
||||
|
||||
static bool _apScanning = false;
|
||||
static uint32_t _lastMaxHeap = 0;
|
||||
|
|
@ -40,39 +42,26 @@ bool Network::setup() {
|
|||
WiFi.mode(WIFI_STA);
|
||||
settings.WIFI.printNetworks();
|
||||
}
|
||||
if(!this->connect()) this->openSoftAP();
|
||||
//if(!this->connect()) this->openSoftAP();
|
||||
return true;
|
||||
}
|
||||
void Network::loop() {
|
||||
this->connect();
|
||||
if(!this->connected() || this->connecting()) return;
|
||||
if(millis() - this->lastEmit > 1500) {
|
||||
this->lastEmit = millis();
|
||||
if(!this->softAPOpened) {
|
||||
while(!this->connect()) {
|
||||
// If we lost our connection
|
||||
connectRetries++;
|
||||
if(connectRetries > 100) {
|
||||
if(!this->connected()) this->openSoftAP();
|
||||
break;
|
||||
}
|
||||
sockEmit.loop();
|
||||
if(this->connected()) {
|
||||
this->emitSockets();
|
||||
this->lastEmit = millis();
|
||||
}
|
||||
connectRetries = 0;
|
||||
}
|
||||
this->emitSockets();
|
||||
this->lastEmit = millis();
|
||||
if(!this->connected()) return;
|
||||
}
|
||||
sockEmit.loop();
|
||||
if(this->connected() && millis() - this->lastMDNS > 60000) {
|
||||
// We are doing this every 60 seconds because of the BS related to
|
||||
// the MDNS library. The original library required manual updates
|
||||
// to the MDNS or it would lose its hostname after 2 minutes.
|
||||
//if(this->lastMDNS != 0) MDNS.setInstanceName(settings.hostname);
|
||||
|
||||
|
||||
// Every 60 seconds we are going to look at wifi connectivity
|
||||
// to get around the roaming issues with ESP32. We will try to do this in an async manner. If
|
||||
// there is a channel that is better we will stop the radio and reconnect
|
||||
// there is a channel that is better we will stop the wifi radio and reconnect
|
||||
if(this->connType == conn_types::wifi && settings.WIFI.roaming && !this->softAPOpened) {
|
||||
// If we are not already scanning then we need to start a passive scan
|
||||
// and only respond if there is a better connection.
|
||||
|
|
@ -237,6 +226,7 @@ void Network::setConnected(conn_types connType) {
|
|||
WiFi.softAPdisconnect(true);
|
||||
WiFi.mode(WIFI_STA);
|
||||
}
|
||||
this->_connecting = false;
|
||||
this->ssid = WiFi.SSID();
|
||||
this->mac = WiFi.BSSIDstr();
|
||||
this->strength = WiFi.RSSI();
|
||||
|
|
@ -248,6 +238,7 @@ void Network::setConnected(conn_types connType) {
|
|||
WiFi.softAPdisconnect(true);
|
||||
WiFi.mode(WIFI_OFF);
|
||||
}
|
||||
this->_connecting = false;
|
||||
this->wifiFallback = false;
|
||||
}
|
||||
sockEmit.begin();
|
||||
|
|
@ -365,8 +356,8 @@ void Network::setConnected(conn_types connType) {
|
|||
this->needsBroadcast = true;
|
||||
}
|
||||
bool Network::connectWired() {
|
||||
//if(this->connType == conn_types::ethernet && ETH.linkUp()) {
|
||||
if(ETH.linkUp()) {
|
||||
// If the ethernet link is re-established then we need to shut down wifi.
|
||||
if(WiFi.status() == WL_CONNECTED) {
|
||||
sockEmit.end();
|
||||
WiFi.disconnect(true);
|
||||
|
|
@ -386,7 +377,11 @@ bool Network::connectWired() {
|
|||
}
|
||||
else
|
||||
Serial.println("Connecting to Wired Ethernet");
|
||||
|
||||
this->connectAttempts++;
|
||||
this->_connecting = true;
|
||||
this->connTarget = conn_types::ethernet;
|
||||
this->connType = conn_types::unset;
|
||||
if(!this->ethStarted) {
|
||||
this->ethStarted = true;
|
||||
WiFi.mode(WIFI_OFF);
|
||||
|
|
@ -415,23 +410,10 @@ bool Network::connectWired() {
|
|||
}
|
||||
else
|
||||
ETH.config(INADDR_NONE, INADDR_NONE, INADDR_NONE, INADDR_NONE);
|
||||
|
||||
uint32_t wait = millis();
|
||||
while(millis() - wait < 14000) {
|
||||
if(ETH.linkUp() && ETH.localIP() != INADDR_NONE) {
|
||||
net.mac = ETH.macAddress();
|
||||
net.setConnected(conn_types::ethernet);
|
||||
return true;
|
||||
}
|
||||
delay(500);
|
||||
}
|
||||
if(settings.connType == conn_types::ethernetpref) {
|
||||
this->wifiFallback = true;
|
||||
return connectWiFi();
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
this->connectStart = millis();
|
||||
return true;
|
||||
}
|
||||
void Network::updateHostname() {
|
||||
if(settings.hostname[0] != '\0' && this->connected()) {
|
||||
|
|
@ -467,11 +449,12 @@ bool Network::connectWiFi() {
|
|||
}
|
||||
else Serial.println("Connecting to AP");
|
||||
this->connectAttempts++;
|
||||
this->connectStart = millis();
|
||||
this->_connecting = true;
|
||||
this->connTarget = conn_types::wifi;
|
||||
this->connType = conn_types::unset;
|
||||
|
||||
WiFi.setSleep(false);
|
||||
WiFi.mode(WIFI_MODE_NULL);
|
||||
//WiFi.onEvent(this->networkEvent);
|
||||
|
||||
if(!settings.IP.dhcp) {
|
||||
if(!WiFi.config(settings.IP.ip, settings.IP.gateway, settings.IP.subnet, settings.IP.dns1, settings.IP.dns2))
|
||||
WiFi.config(INADDR_NONE, INADDR_NONE, INADDR_NONE, INADDR_NONE);
|
||||
|
|
@ -494,80 +477,35 @@ bool Network::connectWiFi() {
|
|||
}
|
||||
else
|
||||
WiFi.begin(settings.WIFI.ssid, settings.WIFI.passphrase);
|
||||
delay(100);
|
||||
int retries = 0;
|
||||
while(retries < 100) {
|
||||
switch(WiFi.status()) {
|
||||
case WL_SCAN_COMPLETED:
|
||||
Serial.println("Status: Scan Completed");
|
||||
break;
|
||||
case WL_CONNECT_FAILED:
|
||||
if(this->connectAttempts == 1) Serial.println();
|
||||
Serial.println("WiFi Module connection failed");
|
||||
return false;
|
||||
case WL_DISCONNECTED:
|
||||
break;
|
||||
case WL_IDLE_STATUS:
|
||||
Serial.print("*");
|
||||
break;
|
||||
case WL_CONNECTED:
|
||||
//WiFi.hostname(settings.hostname);
|
||||
this->ssid = WiFi.SSID();
|
||||
this->mac = WiFi.BSSIDstr();
|
||||
this->strength = WiFi.RSSI();
|
||||
this->channel = WiFi.channel();
|
||||
this->setConnected(conn_types::wifi);
|
||||
WiFi.setSleep(false);
|
||||
return true;
|
||||
case WL_NO_SHIELD:
|
||||
Serial.println("Connection failed - WiFi module not found");
|
||||
return false;
|
||||
case WL_NO_SSID_AVAIL:
|
||||
Serial.print(" Connection failed the SSID ");
|
||||
Serial.print(settings.WIFI.ssid);
|
||||
Serial.println(" could not be found");
|
||||
return false;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
delay(500);
|
||||
if(connectAttempts == 1) Serial.print("*");
|
||||
retries++;
|
||||
}
|
||||
if(this->connectAttempts != 1) {
|
||||
int st = this->getStrengthBySSID(settings.WIFI.ssid);
|
||||
Serial.print("(");
|
||||
Serial.print(st);
|
||||
Serial.print("dBm) ");
|
||||
Serial.println("Failed");
|
||||
//if(disconnected > 0 && st == -100) settings.WIFI.PrintNetworks();
|
||||
disconnected++;
|
||||
}
|
||||
this->connectStart = millis();
|
||||
}
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
bool Network::connect() {
|
||||
if(settings.connType == conn_types::unset) return true;
|
||||
else if(settings.connType == conn_types::ethernet || (settings.connType == conn_types::ethernetpref)) {
|
||||
bool bConnected = this->connectWired();
|
||||
if(!bConnected && settings.connType == conn_types::ethernetpref && settings.WIFI.ssid[0] != '\0') {
|
||||
bConnected = this->connectWiFi();
|
||||
this->wifiFallback = true;
|
||||
if(this->connecting()) {
|
||||
if(this->connType == conn_types::unset) {
|
||||
// If we reached our timeout for the connection then we need to open the soft ap.
|
||||
if(millis() > this->connectStart + CONNECT_TIMEOUT) {
|
||||
if(this->connTarget == conn_types::ethernet && settings.connType == conn_types::ethernetpref && settings.WIFI.ssid[0] != '\0')
|
||||
this->connectWiFi();
|
||||
else {
|
||||
Serial.println("Fell into timeout");
|
||||
this->openSoftAP();
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
return bConnected;
|
||||
else
|
||||
this->setConnected(this->connTarget);
|
||||
}
|
||||
return this->connectWiFi();
|
||||
else if(settings.connType == conn_types::ethernet || settings.connType == conn_types::ethernetpref)
|
||||
this->connectWired();
|
||||
else if(settings.connType == conn_types::wifi && strlen(settings.WIFI.ssid) > 0)
|
||||
this->connectWiFi();
|
||||
else
|
||||
this->openSoftAP();
|
||||
return true;
|
||||
}
|
||||
/* DEPRECATED 03-02-24
|
||||
int Network::getStrengthByMac(const char *macAddr) {
|
||||
int n = WiFi.scanNetworks(true);
|
||||
for(int i = 0; i < n; i++) {
|
||||
if (WiFi.BSSIDstr(i).compareTo(macAddr) == 0)
|
||||
return WiFi.RSSI(i);
|
||||
}
|
||||
return -100;
|
||||
}
|
||||
*/
|
||||
uint32_t Network::getChipId() {
|
||||
uint32_t chipId = 0;
|
||||
uint64_t mac = ESP.getEfuseMac();
|
||||
|
|
@ -645,6 +583,7 @@ bool Network::openSoftAP() {
|
|||
while (!this->connected())
|
||||
{
|
||||
int clients = WiFi.softAPgetStationNum();
|
||||
somfy.loop();
|
||||
webServer.loop();
|
||||
if(millis() - this->lastEmit > 1500) {
|
||||
//if(this->connect()) {}
|
||||
|
|
@ -665,14 +604,22 @@ bool Network::openSoftAP() {
|
|||
|
||||
// If no clients have connected in 3 minutes from starting this server reboot this pig. This will
|
||||
// force a reboot cycle until we have some response. That is unless the SSID has been cleared.
|
||||
if(clients == 0 &&
|
||||
if(clients == 0 && this->connType != conn_types::unset) {
|
||||
Serial.println();
|
||||
Serial.println("Connection Established Stopping AP Mode");
|
||||
this->setConnected(this->connType);
|
||||
return false;
|
||||
}
|
||||
else if(clients == 0 &&
|
||||
(strlen(settings.WIFI.ssid) > 0 || settings.connType == conn_types::ethernet || settings.connType == conn_types::ethernetpref) &&
|
||||
millis() - startTime > 3 * 60000) {
|
||||
Serial.println();
|
||||
Serial.println("Stopping AP Mode");
|
||||
WiFi.softAPdisconnect(true);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if(c == 100) {
|
||||
Serial.println();
|
||||
c = 0;
|
||||
|
|
@ -682,30 +629,41 @@ bool Network::openSoftAP() {
|
|||
return true;
|
||||
}
|
||||
bool Network::connected() {
|
||||
if(this->connType == conn_types::unset) return false;
|
||||
if(this->connecting()) return false;
|
||||
else if(this->connType == conn_types::unset) return false;
|
||||
else if(this->connType == conn_types::wifi) return WiFi.status() == WL_CONNECTED;
|
||||
else if(this->connType == conn_types::ethernet) return ETH.linkUp();
|
||||
else return this->connType != conn_types::unset;
|
||||
return false;
|
||||
}
|
||||
bool Network::connecting() {
|
||||
return this->_connecting;
|
||||
}
|
||||
void Network::networkEvent(WiFiEvent_t event) {
|
||||
switch(event) {
|
||||
case ARDUINO_EVENT_ETH_START:
|
||||
Serial.println("Ethernet Started");
|
||||
case ARDUINO_EVENT_WIFI_READY: Serial.println("WiFi interface ready"); break;
|
||||
case ARDUINO_EVENT_WIFI_SCAN_DONE: Serial.println("Completed scan for access points"); break;
|
||||
case ARDUINO_EVENT_WIFI_STA_START:
|
||||
Serial.println("WiFi station mode started");
|
||||
if(settings.hostname[0] != '\0') WiFi.setHostname(settings.hostname);
|
||||
break;
|
||||
case ARDUINO_EVENT_WIFI_STA_STOP: Serial.println("WiFi clients stopped"); break;
|
||||
case ARDUINO_EVENT_WIFI_STA_CONNECTED: Serial.println("Connected to access point"); break;
|
||||
case ARDUINO_EVENT_WIFI_STA_DISCONNECTED: Serial.println("Disconnected from WiFi access point"); break;
|
||||
case ARDUINO_EVENT_WIFI_STA_AUTHMODE_CHANGE: Serial.println("Authentication mode of access point has changed"); break;
|
||||
case ARDUINO_EVENT_WIFI_STA_GOT_IP:
|
||||
Serial.print("Got WiFi IP: ");
|
||||
Serial.println(WiFi.localIP());
|
||||
net.connType = conn_types::wifi;
|
||||
break;
|
||||
case ARDUINO_EVENT_WIFI_STA_LOST_IP: Serial.println("Lost IP address and IP address is reset to 0"); break;
|
||||
case ARDUINO_EVENT_ETH_GOT_IP:
|
||||
// If the Wifi is connected then drop that connection
|
||||
if(WiFi.status() == WL_CONNECTED) WiFi.disconnect(true);
|
||||
Serial.print("Got Ethernet IP ");
|
||||
Serial.println(ETH.localIP());
|
||||
net.connType = conn_types::ethernet;
|
||||
break;
|
||||
/*
|
||||
case ARDUINO_EVENT_ETH_LOST_IP:
|
||||
Serial.println("Ethernet Lost IP");
|
||||
sockEmit.sendToClients("ethernet", "{\"connected\":false, \"speed\":0,\"fullduplex\":false}");
|
||||
net.connType = conn_types::unset;
|
||||
break;
|
||||
*/
|
||||
case ARDUINO_EVENT_ETH_CONNECTED:
|
||||
Serial.print("Ethernet Connected ");
|
||||
// We don't want to call setConnected if we do not have an IP address yet
|
||||
|
|
@ -714,37 +672,25 @@ void Network::networkEvent(WiFiEvent_t event) {
|
|||
break;
|
||||
case ARDUINO_EVENT_ETH_DISCONNECTED:
|
||||
Serial.println("Ethernet Disconnected");
|
||||
{
|
||||
JsonSockEvent *json = sockEmit.beginEmit("ethernet");
|
||||
json->beginObject();
|
||||
json->addElem("connected", false);
|
||||
json->addElem("speed", (uint8_t)0);
|
||||
json->addElem("fullduplex", false);
|
||||
json->endObject();
|
||||
sockEmit.endEmit();
|
||||
}
|
||||
/*
|
||||
sockEmit.sendToClients("ethernet", "{\"connected\":false,\"speed\":0,\"fullduplex\":false}");
|
||||
*/
|
||||
net.connType = conn_types::unset;
|
||||
break;
|
||||
case ARDUINO_EVENT_ETH_START:
|
||||
Serial.println("Ethernet Started");
|
||||
net.ethStarted = true;
|
||||
break;
|
||||
case ARDUINO_EVENT_ETH_STOP:
|
||||
Serial.println("Ethernet Stopped");
|
||||
net.connType = conn_types::unset;
|
||||
net.ethStarted = false;
|
||||
break;
|
||||
case ARDUINO_EVENT_WIFI_AP_START:
|
||||
Serial.println("WiFi AP Started");
|
||||
net.softAPOpened = true;
|
||||
break;
|
||||
case ARDUINO_EVENT_WIFI_AP_STOP:
|
||||
Serial.println("WiFi AP Stopped");
|
||||
net.softAPOpened = false;
|
||||
break;
|
||||
case ARDUINO_EVENT_WIFI_AP_START:
|
||||
Serial.println("WiFi AP Started");
|
||||
net.softAPOpened = true;
|
||||
break;
|
||||
case ARDUINO_EVENT_WIFI_STA_START:
|
||||
if(settings.hostname[0] != '\0') WiFi.setHostname(settings.hostname);
|
||||
break;
|
||||
case ARDUINO_EVENT_WIFI_STA_CONNECTED:
|
||||
break;
|
||||
default:
|
||||
if(event > ARDUINO_EVENT_ETH_START)
|
||||
Serial.printf("Unknown Ethernet Event %d\n", event);
|
||||
|
|
|
|||
11
Network.h
11
Network.h
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
#ifndef Network_h
|
||||
#define Network_h
|
||||
|
||||
#define CONNECT_TIMEOUT 20000
|
||||
class Network {
|
||||
protected:
|
||||
unsigned long lastEmit = 0;
|
||||
|
|
@ -9,21 +11,24 @@ class Network {
|
|||
int lastRSSI = 0;
|
||||
int lastChannel = 0;
|
||||
int linkSpeed = 0;
|
||||
bool ethStarted = false;
|
||||
bool _connecting = false;
|
||||
public:
|
||||
bool ethStarted = false;
|
||||
bool wifiFallback = false;
|
||||
bool softAPOpened = false;
|
||||
bool needsBroadcast = true;
|
||||
conn_types connType = conn_types::unset;
|
||||
conn_types connTarget = conn_types::unset;
|
||||
bool connected();
|
||||
bool connecting();
|
||||
String ssid;
|
||||
String mac;
|
||||
int channel;
|
||||
int strength;
|
||||
int disconnected = 0;
|
||||
int connectAttempts = 0;
|
||||
long connectStart = 0;
|
||||
long connectTime = 0;
|
||||
uint32_t connectStart = 0;
|
||||
uint32_t connectTime = 0;
|
||||
bool openSoftAP();
|
||||
bool connect();
|
||||
bool connectWiFi();
|
||||
|
|
|
|||
130
Sockets.cpp
130
Sockets.cpp
|
|
@ -82,96 +82,6 @@ void SocketEmitter::loop() {
|
|||
this->initClients();
|
||||
sockServer.loop();
|
||||
}
|
||||
/*
|
||||
ClientSocketEvent::ClientSocketEvent() { this->msg[0] = 0x00; }
|
||||
ClientSocketEvent::ClientSocketEvent(const char *evt) { snprintf(this->msg, sizeof(this->msg), "42[%s,]", evt); }
|
||||
//ClientSocketEvent::ClientSocketEvent(const char *evt, const char *payload) { snprintf(this->msg, sizeof(this->msg), "42[%s,%s]", evt, payload); }
|
||||
void ClientSocketEvent::beginEmit(const char *evt) { snprintf(this->msg, sizeof(this->msg), "42[%s,", evt); }
|
||||
void ClientSocketEvent::endEmit() { this->_safecat("]"); }
|
||||
void ClientSocketEvent::appendMessage(const char *text) {
|
||||
uint16_t len = strlen(this->msg);
|
||||
this->msg[len - 1] = '\0';
|
||||
strcat(this->msg, text);
|
||||
strcat(this->msg, "]");
|
||||
}
|
||||
void ClientSocketEvent::beginObject(const char *name) {
|
||||
if(name && strlen(name) > 0) this->appendElem(name);
|
||||
else if(!this->_nocomma) this->_safecat(",");
|
||||
this->_safecat("{");
|
||||
this->_objects++;
|
||||
this->_nocomma = true;
|
||||
}
|
||||
void ClientSocketEvent::endObject() {
|
||||
//if(strlen(this->buff) + 1 > this->buffSize - 1) this->send();
|
||||
this->_safecat("}");
|
||||
this->_objects--;
|
||||
this->_nocomma = false;
|
||||
}
|
||||
void ClientSocketEvent::beginArray(const char *name) {
|
||||
if(name && strlen(name) > 0) this->appendElem(name);
|
||||
else if(!this->_nocomma) this->_safecat(",");
|
||||
this->_safecat("[");
|
||||
this->_arrays++;
|
||||
this->_nocomma = true;
|
||||
}
|
||||
void ClientSocketEvent::endArray() {
|
||||
//if(strlen(this->buff) + 1 > this->buffSize - 1) this->send();
|
||||
this->_safecat("]");
|
||||
this->_arrays--;
|
||||
this->_nocomma = false;
|
||||
}
|
||||
|
||||
|
||||
void ClientSocketEvent::appendElem(const char *name) {
|
||||
if(!this->_nocomma) this->_safecat(",");
|
||||
if(name && strlen(name) > 0) {
|
||||
this->_safecat(name, true);
|
||||
this->_safecat(":");
|
||||
}
|
||||
this->_nocomma = false;
|
||||
}
|
||||
|
||||
void ClientSocketEvent::addElem(const char *name, const char *val) {
|
||||
if(!val) return;
|
||||
this->appendElem(name);
|
||||
this->_safecat(val, true);
|
||||
}
|
||||
void ClientSocketEvent::addElem(const char *val) { this->addElem(nullptr, val); }
|
||||
void ClientSocketEvent::addElem(float fval) { sprintf(this->_numbuff, "%.4f", fval); this->_appendNumber(nullptr); }
|
||||
void ClientSocketEvent::addElem(int8_t nval) { sprintf(this->_numbuff, "%d", nval); this->_appendNumber(nullptr); }
|
||||
void ClientSocketEvent::addElem(uint8_t nval) { sprintf(this->_numbuff, "%u", nval); this->_appendNumber(nullptr); }
|
||||
void ClientSocketEvent::addElem(int16_t nval) { sprintf(this->_numbuff, "%d", nval); this->_appendNumber(nullptr); }
|
||||
void ClientSocketEvent::addElem(uint16_t nval) { sprintf(this->_numbuff, "%u", nval); this->_appendNumber(nullptr); }
|
||||
void ClientSocketEvent::addElem(int32_t nval) { sprintf(this->_numbuff, "%ld", (long)nval); this->_appendNumber(nullptr); }
|
||||
void ClientSocketEvent::addElem(uint32_t nval) { sprintf(this->_numbuff, "%lu", (unsigned long)nval); this->_appendNumber(nullptr); }
|
||||
void ClientSocketEvent::addElem(int64_t lval) { sprintf(this->_numbuff, "%lld", (long long)lval); this->_appendNumber(nullptr); }
|
||||
void ClientSocketEvent::addElem(uint64_t lval) { sprintf(this->_numbuff, "%llu", (unsigned long long)lval); this->_appendNumber(nullptr); }
|
||||
void ClientSocketEvent::addElem(bool bval) { strcpy(this->_numbuff, bval ? "true" : "false"); this->_appendNumber(nullptr); }
|
||||
|
||||
void ClientSocketEvent::addElem(const char *name, float fval) { sprintf(this->_numbuff, "%.4f", fval); this->_appendNumber(name); }
|
||||
void ClientSocketEvent::addElem(const char *name, int8_t nval) { sprintf(this->_numbuff, "%d", nval); this->_appendNumber(name); }
|
||||
void ClientSocketEvent::addElem(const char *name, uint8_t nval) { sprintf(this->_numbuff, "%u", nval); this->_appendNumber(name); }
|
||||
void ClientSocketEvent::addElem(const char *name, int16_t nval) { sprintf(this->_numbuff, "%d", nval); this->_appendNumber(name); }
|
||||
void ClientSocketEvent::addElem(const char *name, uint16_t nval) { sprintf(this->_numbuff, "%u", nval); this->_appendNumber(name); }
|
||||
void ClientSocketEvent::addElem(const char *name, int32_t nval) { sprintf(this->_numbuff, "%ld", (long)nval); this->_appendNumber(name); }
|
||||
void ClientSocketEvent::addElem(const char *name, uint32_t nval) { sprintf(this->_numbuff, "%lu", (unsigned long)nval); this->_appendNumber(name); }
|
||||
void ClientSocketEvent::addElem(const char *name, int64_t lval) { sprintf(this->_numbuff, "%lld", (long long)lval); this->_appendNumber(name); }
|
||||
void ClientSocketEvent::addElem(const char *name, uint64_t lval) { sprintf(this->_numbuff, "%llu", (unsigned long long)lval); this->_appendNumber(name); }
|
||||
void ClientSocketEvent::addElem(const char *name, bool bval) { strcpy(this->_numbuff, bval ? "true" : "false"); this->_appendNumber(name); }
|
||||
|
||||
void ClientSocketEvent::_safecat(const char *val, bool escape) {
|
||||
size_t len = strlen(val) + strlen(this->msg);
|
||||
if(escape) len += 2;
|
||||
if(len >= sizeof(this->msg)) {
|
||||
//this->send();
|
||||
}
|
||||
if(escape) strcat(this->msg, "\"");
|
||||
strcat(this->msg, val);
|
||||
if(escape) strcat(this->msg, "\"");
|
||||
}
|
||||
void ClientSocketEvent::_appendNumber(const char *name) { this->appendElem(name); this->_safecat(this->_numbuff); }
|
||||
*/
|
||||
|
||||
JsonSockEvent *SocketEmitter::beginEmit(const char *evt) {
|
||||
this->json.beginEvent(&sockServer, evt, g_response, sizeof(g_response));
|
||||
return &this->json;
|
||||
|
|
@ -189,46 +99,6 @@ uint8_t SocketEmitter::activeClients(uint8_t room) {
|
|||
if(room < SOCK_MAX_ROOMS) return this->rooms[room].activeClients();
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
bool SocketEmitter::sendToRoom(uint8_t room, ClientSocketEvent *evt) {
|
||||
if(room < SOCK_MAX_ROOMS) {
|
||||
room_t *r = &this->rooms[room];
|
||||
for(uint8_t i = 0; i < sizeof(r->clients); i++) {
|
||||
if(r->clients[i] != 255) this->sendToClient(r->clients[i], evt);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool SocketEmitter::sendToClients(ClientSocketEvent *evt) {
|
||||
if(evt->msg[strlen(evt->msg) - 1] != ']') strcat(evt->msg, "]");
|
||||
return sockServer.broadcastTXT(evt->msg);
|
||||
}
|
||||
bool SocketEmitter::sendToClient(uint8_t num, ClientSocketEvent *evt) {
|
||||
if(evt->msg[strlen(evt->msg) - 1] != ']') strcat(evt->msg, "]");
|
||||
return sockServer.sendTXT(num, evt->msg);
|
||||
}
|
||||
bool SocketEmitter::sendToClients(const char *evt, const char *payload) {
|
||||
if(settings.status == DS_FWUPDATE) return true;
|
||||
this->evt.prepareMessage(evt, payload);
|
||||
return sockServer.broadcastTXT(this->evt.msg);
|
||||
}
|
||||
bool SocketEmitter::sendToClient(uint8_t num, const char *evt, const char *payload) {
|
||||
if(settings.status == DS_FWUPDATE) return true;
|
||||
this->evt.prepareMessage(evt, payload);
|
||||
return sockServer.sendTXT(num, this->evt.msg);
|
||||
}
|
||||
bool SocketEmitter::sendToClient(uint8_t num, const char *evt, JsonDocument &doc) {
|
||||
if(settings.status == DS_FWUPDATE) return true;
|
||||
this->evt.prepareMessage(evt, doc);
|
||||
return sockServer.sendTXT(num, this->evt.msg);
|
||||
}
|
||||
bool SocketEmitter::sendToClients(const char *evt, JsonDocument &doc) {
|
||||
if(settings.status == DS_FWUPDATE) return true;
|
||||
this->evt.prepareMessage(evt, doc);
|
||||
return sockServer.broadcastTXT(this->evt.msg);
|
||||
}
|
||||
*/
|
||||
void SocketEmitter::initClients() {
|
||||
for(uint8_t i = 0; i < sizeof(this->newClients); i++) {
|
||||
uint8_t num = this->newClients[i];
|
||||
|
|
|
|||
63
Sockets.h
63
Sockets.h
|
|
@ -13,60 +13,6 @@ struct room_t {
|
|||
bool join(uint8_t num);
|
||||
bool leave(uint8_t num);
|
||||
};
|
||||
/*
|
||||
class ClientSocketEvent {
|
||||
private:
|
||||
uint8_t _objects = 0;
|
||||
uint8_t _arrays = 0;
|
||||
bool _nocomma = true;
|
||||
char _numbuff[25] = {0};
|
||||
protected:
|
||||
void _safecat(const char *val, bool escape = false);
|
||||
void _appendNumber(const char *name);
|
||||
public:
|
||||
ClientSocketEvent();
|
||||
ClientSocketEvent(const char *evt);
|
||||
//ClientSocketEvent(const char *evt, const char *data);
|
||||
char msg[2048] = "";
|
||||
void beginEmit(const char *evt);
|
||||
void endEmit();
|
||||
|
||||
void prepareMessage(const char *evt, const char *data);
|
||||
void prepareMessage(const char *evt, JsonDocument &doc);
|
||||
void appendMessage(const char *text);
|
||||
void appendElement(const char *elem, const char *val);
|
||||
|
||||
void beginObject(const char *name = nullptr);
|
||||
void endObject();
|
||||
void beginArray(const char *name = nullptr);
|
||||
void endArray();
|
||||
|
||||
void appendElem(const char *name = nullptr);
|
||||
void addElem(const char* val);
|
||||
void addElem(float fval);
|
||||
void addElem(int8_t nval);
|
||||
void addElem(uint8_t nval);
|
||||
void addElem(int16_t nval);
|
||||
void addElem(uint16_t nval);
|
||||
void addElem(int32_t nval);
|
||||
void addElem(uint32_t nval);
|
||||
void addElem(int64_t lval);
|
||||
void addElem(uint64_t lval);
|
||||
void addElem(bool bval);
|
||||
|
||||
void addElem(const char* name, float fval);
|
||||
void addElem(const char* name, int8_t nval);
|
||||
void addElem(const char* name, uint8_t nval);
|
||||
void addElem(const char* name, int16_t nval);
|
||||
void addElem(const char* name, uint16_t nval);
|
||||
void addElem(const char* name, int32_t nval);
|
||||
void addElem(const char* name, uint32_t nval);
|
||||
void addElem(const char* name, int64_t lval);
|
||||
void addElem(const char* name, uint64_t lval);
|
||||
void addElem(const char* name, bool bval);
|
||||
void addElem(const char *name, const char *val);
|
||||
};
|
||||
*/
|
||||
class SocketEmitter {
|
||||
protected:
|
||||
uint8_t newclients = 0;
|
||||
|
|
@ -86,15 +32,6 @@ class SocketEmitter {
|
|||
JsonSockEvent * beginEmit(const char *evt);
|
||||
void endEmit(uint8_t num = 255);
|
||||
void endEmitRoom(uint8_t num);
|
||||
/*
|
||||
bool sendToRoom(uint8_t room, ClientSocketEvent *evt);
|
||||
bool sendToClients(ClientSocketEvent *evt);
|
||||
bool sendToClient(uint8_t num, ClientSocketEvent *evt);
|
||||
bool sendToClients(const char *evt, const char *data);
|
||||
bool sendToClient(uint8_t num, const char *evt, const char *data);
|
||||
bool sendToClients(const char *evt, JsonDocument &doc);
|
||||
bool sendToClient(uint8_t num, const char *evt, JsonDocument &doc);
|
||||
*/
|
||||
static void wsEvent(uint8_t num, WStype_t type, uint8_t *payload, size_t length);
|
||||
};
|
||||
#endif
|
||||
|
|
|
|||
68
Somfy.cpp
68
Somfy.cpp
|
|
@ -57,6 +57,8 @@ somfy_commands translateSomfyCommand(const String& string) {
|
|||
else if (string.equalsIgnoreCase("Flag")) return somfy_commands::Flag;
|
||||
else if (string.equalsIgnoreCase("Sensor")) return somfy_commands::Sensor;
|
||||
else if (string.equalsIgnoreCase("Toggle")) return somfy_commands::Toggle;
|
||||
else if (string.equalsIgnoreCase("Favorite")) return somfy_commands::Fav;
|
||||
else if (string.startsWith("fav") || string.startsWith("FAV")) return somfy_commands::Fav;
|
||||
else if (string.startsWith("mud") || string.startsWith("MUD")) return somfy_commands::MyUpDown;
|
||||
else if (string.startsWith("md") || string.startsWith("MD")) return somfy_commands::MyDown;
|
||||
else if (string.startsWith("ud") || string.startsWith("UD")) return somfy_commands::UpDown;
|
||||
|
|
@ -104,6 +106,8 @@ String translateSomfyCommand(const somfy_commands cmd) {
|
|||
return "Sensor";
|
||||
case somfy_commands::Toggle:
|
||||
return "Toggle";
|
||||
case somfy_commands::Fav:
|
||||
return "Favorite";
|
||||
default:
|
||||
return "Unknown(" + String((uint8_t)cmd) + ")";
|
||||
}
|
||||
|
|
@ -154,7 +158,11 @@ void somfy_frame_t::decodeFrame(byte* frame) {
|
|||
this->remoteAddress = (decoded[6] + (decoded[5] << 8) + (decoded[4] << 16));
|
||||
this->valid = this->checksum == checksum && this->remoteAddress > 0 && this->remoteAddress < 16777215;
|
||||
if (this->cmd != somfy_commands::Sensor && this->valid) this->valid = (this->rollingCode > 0);
|
||||
|
||||
if (this->valid) {
|
||||
uint8_t csc80 = 0;
|
||||
uint8_t cs80 = 0;
|
||||
|
||||
// Check for valid command.
|
||||
switch (this->cmd) {
|
||||
//case somfy_commands::Unknown0:
|
||||
|
|
@ -177,7 +185,24 @@ void somfy_frame_t::decodeFrame(byte* frame) {
|
|||
case somfy_commands::StepUp:
|
||||
case somfy_commands::StepDown:
|
||||
case somfy_commands::Toggle:
|
||||
case somfy_commands::Fav:
|
||||
// These must be 80 bit commands
|
||||
csc80 = (decoded[9] & 0x0F);
|
||||
cs80 = (((decoded[7] & 0xF0) >> 4) ^ ((decoded[8] & 0xF0) >> 4));
|
||||
cs80 ^= ((decoded[9] & 0xF0) >> 4);
|
||||
cs80 ^= (decoded[7] & 0x0F);
|
||||
cs80 ^= (decoded[8] & 0x0F);
|
||||
//cs80 = (((decoded[7] & 0xF0) >> 4) ^ ((decoded[8] & 0xF0) >> 4) ^ ((decoded[9] & 0xF0) >> 4) ^ (decoded[7] & 0x0F) ^ (decoded[8] & 0x0F));
|
||||
if(csc80 != cs80) this->valid = false;
|
||||
/*
|
||||
uint8_t ai = ((decoded[7] & 0xF0) >> 4);
|
||||
uint8_t aj = ((decoded[8] & 0xF0) >> 4);
|
||||
uint8_t ak = ((decoded[9] & 0xF0) >> 4);
|
||||
uint8_t al = (decoded[7] & 0x0F);
|
||||
uint8_t am = (decoded[8] & 0x0F);
|
||||
uint8_t an = (decoded[9] & 0x0F);
|
||||
cs80 = ai ^ aj ^ ak ^ al ^ am;
|
||||
*/
|
||||
break;
|
||||
default:
|
||||
this->valid = false;
|
||||
|
|
@ -644,8 +669,10 @@ void SomfyRoom::clear() {
|
|||
void SomfyGroup::clear() {
|
||||
this->setGroupId(255);
|
||||
this->setRemoteAddress(0);
|
||||
this->repeats = 1;
|
||||
memset(&this->linkedShades[0], 0x00, sizeof(this->linkedShades));
|
||||
this->repeats = 0;
|
||||
this->roomId = 0;
|
||||
this->name[0] = 0x00;
|
||||
memset(&this->linkedShades, 0x00, sizeof(this->linkedShades));
|
||||
}
|
||||
bool SomfyShade::linkRemote(uint32_t address, uint16_t rollingCode) {
|
||||
// Check to see if the remote is already linked. If it is
|
||||
|
|
@ -830,10 +857,13 @@ bool SomfyShade::isAtTarget() {
|
|||
else if(this->tiltType == tilt_types::none) return fabs(this->currentPos - this->target) < epsilon;
|
||||
return fabs(this->currentPos - this->target) < epsilon && fabs(this->currentTiltPos - this->tiltTarget) < epsilon;
|
||||
}
|
||||
bool SomfyRemote::simMy() { return (this->flags & static_cast<uint8_t>(somfy_flags_t::SimMy)) > 0; }
|
||||
void SomfyRemote::setSimMy(bool bSimMy) { bSimMy ? this->flags |= static_cast<uint8_t>(somfy_flags_t::SimMy) : this->flags &= ~(static_cast<uint8_t>(somfy_flags_t::SimMy)); }
|
||||
bool SomfyRemote::hasSunSensor() { return (this->flags & static_cast<uint8_t>(somfy_flags_t::SunSensor)) > 0;}
|
||||
bool SomfyRemote::hasLight() { return (this->flags & static_cast<uint8_t>(somfy_flags_t::Light)) > 0; }
|
||||
void SomfyRemote::setSunSensor(bool bHasSensor ) { bHasSensor ? this->flags |= static_cast<uint8_t>(somfy_flags_t::SunSensor) : this->flags &= ~(static_cast<uint8_t>(somfy_flags_t::SunSensor)); }
|
||||
void SomfyRemote::setLight(bool bHasLight ) { bHasLight ? this->flags |= static_cast<uint8_t>(somfy_flags_t::Light) : this->flags &= ~(static_cast<uint8_t>(somfy_flags_t::Light)); }
|
||||
|
||||
void SomfyGroup::updateFlags() {
|
||||
uint8_t oldFlags = this->flags;
|
||||
this->flags = 0;
|
||||
|
|
@ -2772,7 +2802,12 @@ void SomfyShade::moveToMyPosition() {
|
|||
if(this->tiltType != tilt_types::tiltonly && this->myPos >= 0.0f && this->myPos <= 100.0f) this->p_target(this->myPos);
|
||||
if(this->myTiltPos >= 0.0f && this->myTiltPos <= 100.0f) this->p_tiltTarget(this->myTiltPos);
|
||||
this->settingPos = false;
|
||||
SomfyRemote::sendCommand(somfy_commands::My, this->repeats);
|
||||
if(this->simMy()) {
|
||||
Serial.print("Moving to simulated favorite\n");
|
||||
this->moveToTarget(this->myPos, this->myTiltPos);
|
||||
}
|
||||
else
|
||||
SomfyRemote::sendCommand(somfy_commands::My, this->repeats);
|
||||
}
|
||||
void SomfyShade::sendCommand(somfy_commands cmd) { this->sendCommand(cmd, this->repeats); }
|
||||
void SomfyShade::sendCommand(somfy_commands cmd, uint8_t repeat) {
|
||||
|
|
@ -3098,6 +3133,7 @@ int8_t SomfyShade::fromJSON(JsonObject &obj) {
|
|||
if(obj.containsKey("bitLength")) this->bitLength = obj["bitLength"];
|
||||
if(obj.containsKey("proto")) this->proto = static_cast<radio_proto>(obj["proto"].as<uint8_t>());
|
||||
if(obj.containsKey("sunSensor")) this->setSunSensor(obj["sunSensor"]);
|
||||
if(obj.containsKey("simMy")) this->setSimMy(obj["simMy"]);
|
||||
if(obj.containsKey("light")) this->setLight(obj["light"]);
|
||||
if(obj.containsKey("gpioFlags")) this->gpioFlags = obj["gpioFlags"];
|
||||
if(obj.containsKey("gpioLLTrigger")) {
|
||||
|
|
@ -3180,24 +3216,6 @@ int8_t SomfyShade::fromJSON(JsonObject &obj) {
|
|||
}
|
||||
return err;
|
||||
}
|
||||
/*
|
||||
bool SomfyShade::toJSONRef(JsonObject &obj) {
|
||||
obj["shadeId"] = this->getShadeId();
|
||||
obj["roomId"] = this->roomId;
|
||||
obj["name"] = this->name;
|
||||
obj["remoteAddress"] = this->m_remoteAddress;
|
||||
obj["paired"] = this->paired;
|
||||
obj["shadeType"] = static_cast<uint8_t>(this->shadeType);
|
||||
obj["bitLength"] = this->bitLength;
|
||||
obj["proto"] = static_cast<uint8_t>(this->proto);
|
||||
obj["flags"] = this->flags;
|
||||
obj["sunSensor"] = this->hasSunSensor();
|
||||
obj["hasLight"] = this->hasLight();
|
||||
obj["repeats"] = this->repeats;
|
||||
SomfyRemote::toJSON(obj);
|
||||
return true;
|
||||
}
|
||||
*/
|
||||
void SomfyShade::toJSONRef(JsonResponse &json) {
|
||||
json.addElem("shadeId", this->getShadeId());
|
||||
json.addElem("roomId", this->roomId);
|
||||
|
|
@ -3249,6 +3267,7 @@ void SomfyShade::toJSON(JsonResponse &json) {
|
|||
json.addElem("gpioDown", this->gpioDown);
|
||||
json.addElem("gpioMy", this->gpioMy);
|
||||
json.addElem("gpioLLTrigger", ((this->gpioFlags & (uint8_t)gpio_flags_t::LowLevelTrigger) == 0) ? false : true);
|
||||
json.addElem("simMy", this->simMy());
|
||||
json.beginArray("linkedRemotes");
|
||||
for(uint8_t i = 0; i < SOMFY_MAX_LINKED_REMOTES; i++) {
|
||||
SomfyLinkedRemote &lremote = this->linkedRemotes[i];
|
||||
|
|
@ -4093,13 +4112,6 @@ void SomfyShadeController::toJSONRepeaters(JsonResponse &json) {
|
|||
if(somfy.repeaters[i] != 0) json.addElem((uint8_t)somfy.repeaters[i]);
|
||||
}
|
||||
}
|
||||
bool SomfyShadeController::toJSONRepeaters(JsonArray &arr) {
|
||||
for(uint8_t i = 0; i < SOMFY_MAX_REPEATERS; i++) {
|
||||
if(somfy.repeaters[i] != 0) arr.add(somfy.repeaters[i]);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void SomfyShadeController::loop() {
|
||||
this->transceiver.loop();
|
||||
for(uint8_t i = 0; i < SOMFY_MAX_SHADES; i++) {
|
||||
|
|
|
|||
19
Somfy.h
19
Somfy.h
|
|
@ -47,6 +47,7 @@ enum class somfy_commands : byte {
|
|||
RTWProto = 0xF, // RTW Protocol
|
||||
// Command extensions for 80 bit frames
|
||||
StepUp = 0x8B,
|
||||
Fav = 0x90,
|
||||
};
|
||||
enum class group_types : byte {
|
||||
channel = 0x00
|
||||
|
|
@ -155,7 +156,8 @@ enum class somfy_flags_t : byte {
|
|||
Light = 0x08,
|
||||
Windy = 0x10,
|
||||
Sunny = 0x20,
|
||||
Lighted = 0x40
|
||||
Lighted = 0x40,
|
||||
SimMy = 0x80
|
||||
};
|
||||
enum class gpio_flags_t : byte {
|
||||
LowLevelTrigger = 0x01
|
||||
|
|
@ -181,6 +183,7 @@ struct somfy_frame_t {
|
|||
uint32_t await = 0;
|
||||
uint8_t bitLength = 56;
|
||||
uint16_t pulseCount = 0;
|
||||
uint8_t stepSize = 0;
|
||||
void print();
|
||||
void encodeFrame(byte *frame);
|
||||
void decodeFrame(byte* frame);
|
||||
|
|
@ -197,7 +200,6 @@ class SomfyRoom {
|
|||
void clear();
|
||||
bool save();
|
||||
bool fromJSON(JsonObject &obj);
|
||||
//bool toJSON(JsonObject &obj);
|
||||
void toJSON(JsonResponse &json);
|
||||
void emitState(const char *evt = "roomState");
|
||||
void emitState(uint8_t num, const char *evt = "roomState");
|
||||
|
|
@ -228,7 +230,6 @@ class SomfyRemote {
|
|||
uint8_t repeats = 1;
|
||||
virtual bool isLastCommand(somfy_commands cmd);
|
||||
char *getRemotePrefId() {return m_remotePrefId;}
|
||||
//virtual bool toJSON(JsonObject &obj);
|
||||
virtual void toJSON(JsonResponse &json);
|
||||
virtual void setRemoteAddress(uint32_t address);
|
||||
virtual uint32_t getRemoteAddress();
|
||||
|
|
@ -236,8 +237,10 @@ class SomfyRemote {
|
|||
virtual uint16_t setRollingCode(uint16_t code);
|
||||
bool hasSunSensor();
|
||||
bool hasLight();
|
||||
bool simMy();
|
||||
void setSunSensor(bool bHasSensor);
|
||||
void setLight(bool bHasLight);
|
||||
void setSimMy(bool bSimMy);
|
||||
virtual void sendCommand(somfy_commands cmd);
|
||||
virtual void sendCommand(somfy_commands cmd, uint8_t repeat);
|
||||
void sendSensorCommand(int8_t isWindy, int8_t isSunny, uint8_t repeat);
|
||||
|
|
@ -280,10 +283,8 @@ class SomfyShade : public SomfyRemote {
|
|||
#ifdef USE_NVS
|
||||
void load();
|
||||
#endif
|
||||
//somfy_tx_queue_t txQueue;
|
||||
float currentPos = 0.0f;
|
||||
float currentTiltPos = 0.0f;
|
||||
//uint16_t movement = 0;
|
||||
int8_t lastMovement = 0;
|
||||
int8_t direction = 0; // 0 = stopped, 1=down, -1=up.
|
||||
int8_t tiltDirection = 0; // 0=stopped, 1=clockwise, -1=counter clockwise
|
||||
|
|
@ -294,10 +295,8 @@ class SomfyShade : public SomfyRemote {
|
|||
SomfyLinkedRemote linkedRemotes[SOMFY_MAX_LINKED_REMOTES];
|
||||
bool paired = false;
|
||||
int8_t validateJSON(JsonObject &obj);
|
||||
//bool toJSONRef(JsonObject &obj);
|
||||
void toJSONRef(JsonResponse &json);
|
||||
int8_t fromJSON(JsonObject &obj);
|
||||
//bool toJSON(JsonObject &obj) override;
|
||||
void toJSON(JsonResponse &json) override;
|
||||
|
||||
char name[21] = "";
|
||||
|
|
@ -548,16 +547,10 @@ class SomfyShadeController {
|
|||
SomfyGroup groups[SOMFY_MAX_GROUPS];
|
||||
bool linkRepeater(uint32_t address);
|
||||
bool unlinkRepeater(uint32_t address);
|
||||
//bool toJSON(DynamicJsonDocument &doc);
|
||||
//bool toJSON(JsonObject &obj);
|
||||
//bool toJSONRooms(JsonArray &arr);
|
||||
//bool toJSONShades(JsonArray &arr);
|
||||
//bool toJSONGroups(JsonArray &arr);
|
||||
void toJSONShades(JsonResponse &json);
|
||||
void toJSONRooms(JsonResponse &json);
|
||||
void toJSONGroups(JsonResponse &json);
|
||||
void toJSONRepeaters(JsonResponse &json);
|
||||
bool toJSONRepeaters(JsonArray &arr);
|
||||
uint8_t repeaterCount();
|
||||
uint8_t roomCount();
|
||||
uint8_t shadeCount();
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -1 +1 @@
|
|||
2.4.1
|
||||
2.4.3
|
||||
|
|
@ -8,9 +8,9 @@
|
|||
<meta name="apple-mobile-web-app-title" content="ESPSomfy RTS App">
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black">
|
||||
|
||||
<link rel="stylesheet" href="main.css?v=2.4.2r" type="text/css" />
|
||||
<link rel="stylesheet" href="widgets.css?v=2.4.2r" type="text/css" />
|
||||
<link rel="stylesheet" href="icons.css?v=2.4.2r" type="text/css" />
|
||||
<link rel="stylesheet" href="main.css?v=2.4.3b" type="text/css" />
|
||||
<link rel="stylesheet" href="widgets.css?v=2.4.3b" type="text/css" />
|
||||
<link rel="stylesheet" href="icons.css?v=2.4.3b" type="text/css" />
|
||||
<link rel="icon" type="image/png" href="favicon.png" />
|
||||
|
||||
<!-- iPad retina icon -->
|
||||
|
|
@ -609,6 +609,13 @@
|
|||
<label for="cbFlipPosition" style="display:block;font-size:1em;margin-top:0px;margin-left:7px;display:inline-block;">Invert Position (expressed in % of open)</label>
|
||||
</div>
|
||||
</div>
|
||||
<div style="margin-top:-10px;" id="divSimMy">
|
||||
<div class="field-group">
|
||||
<input id="cbSimMy" name="simMy" data-bind="simMy" type="checkbox" style="" />
|
||||
<label for="cbSimMy" style="display:block;font-size:1em;margin-top:0px;margin-left:7px;display:inline-block;">Simulate Favorite Position</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div classs="field-group" style="display:inline-block;">
|
||||
<label for="selRepeatCommnds" style="cursor:pointer;color:#00bcd4;margin-right:4px;">Repeat Commands</label>
|
||||
<select id="selRepeatCommands" data-bind="repeats" data-datatype="int" style="width:127px;">
|
||||
|
|
|
|||
|
|
@ -1270,7 +1270,7 @@ var security = new Security();
|
|||
|
||||
class General {
|
||||
initialized = false;
|
||||
appVersion = 'v2.4.2';
|
||||
appVersion = 'v2.4.3';
|
||||
reloadApp = false;
|
||||
init() {
|
||||
if (this.initialized) return;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue