#include #include #include #include #include //#define LED_WF (14) //#define LED_MQ (12) //#define LED_WRK (13) #define TUYA_OPEN "55aa000600056604000100" #define TUYA_CLOSE "55aa000600056604000101" #define TUYA_STOP "55aa000600056604000102" // set position percentage #define TUYA_SET_POSITION "55aa0006000865020004000000" // and 1 byte (0x00-0x64) // enable/disable reversed motor direction #define TUYA_DISABLE_REVERSING "55aa000600056700000100" #define TUYA_ENABLE_REVERSING "55aa000600056700000101" #define CURT_CLOSING (1) #define CURT_OPENING (2) #define CURT_IDLE (0) const char* ssid = "wf-home"; const char* password = "0ndthnrf"; const char* mqtt_server = "192.168.1.250"; unsigned long cRun = millis(); double curr; int nSec, nSampl; uint8_t buffer[1024]; bool reversed, curtOpened, curtClosed; float position; uint8_t offset; uint8_t cur_operation; uint8_t crc; AsyncMqttClient mqttClient; Ticker mqttReconnectTimer; WiFiEventHandler wifiConnectHandler; WiFiEventHandler wifiDisconnectHandler; Ticker wifiReconnectTimer; SoftwareSerial softSer(D7, D8); void connectToWifi(); void connectToMqtt(); void onWifiConnect(const WiFiEventStationModeGotIP& event); void onWifiDisconnect(const WiFiEventStationModeDisconnected& event); void onMqttConnect(bool sessionPresent); void onMqttDisconnect(AsyncMqttClientDisconnectReason reason); void onMqttSubscribe(uint16_t packetId, uint8_t qos); void onMqttMessage(char* topic, char* payload, AsyncMqttClientMessageProperties properties, size_t len, size_t index, size_t total); void readByte(uint8_t data); void writeByte(uint8_t data); void writeHex(std::string data); void setup(){ Serial.begin(9600); pinMode(D7, INPUT); pinMode(D8, OUTPUT); softSer.begin(9600);//, SWSERIAL_8N1, D5, D6, false); WiFi.mode(WIFI_STA); WiFi.hostname("Cur-MidRoom"); ArduinoOTA.onStart([]() { Serial1.println("Start Update"); // "Начало OTA-апдейта" }); ArduinoOTA.onEnd([]() { Serial1.println("\nEnd Update"); // "Завершение OTA-апдейта" }); ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) { //Serial1.printf("Progress: %u%%\r", (progress / (total / 100))); }); ArduinoOTA.onError([](ota_error_t error) { Serial1.printf("Error[%u]: ", error); if (error == OTA_AUTH_ERROR) Serial1.println("Auth Failed"); // "Ошибка при аутентификации" else if (error == OTA_BEGIN_ERROR) Serial1.println("Begin Failed"); // "Ошибка при начале OTA-апдейта" else if (error == OTA_CONNECT_ERROR) Serial1.println("Connect Failed"); // "Ошибка при подключении" else if (error == OTA_RECEIVE_ERROR) Serial1.println("Receive Failed"); // "Ошибка при получении данных" else if (error == OTA_END_ERROR) Serial1.println("End Failed"); // "Ошибка при завершении OTA-апдейта" }); ArduinoOTA.begin(); wifiConnectHandler = WiFi.onStationModeGotIP(onWifiConnect); wifiDisconnectHandler = WiFi.onStationModeDisconnected(onWifiDisconnect); mqttClient.onConnect(onMqttConnect); mqttClient.onDisconnect(onMqttDisconnect); mqttClient.onSubscribe(onMqttSubscribe); mqttClient.onMessage(onMqttMessage); mqttClient.setServer(mqtt_server, 1883); mqttClient.setClientId("Cur_MidRoom"); //pinMode(LED_WF, OUTPUT); //pinMode(LED_MQ, OUTPUT); //pinMode(LED_WRK, OUTPUT); //pinMode(5, INPUT_PULLUP); //digitalWrite(LED_WF, LOW); //digitalWrite(LED_MQ, LOW); //digitalWrite(LED_WRK, LOW); connectToWifi(); nSec = 0; curr = -1; nSampl = 0; Serial.println("Start"); } void loop(){ static bool led_wrk = false; uint8_t in_b; ArduinoOTA.handle(); crc = 0; offset = 0; while(softSer.available()){ in_b = softSer.read(); Serial.print(in_b, 16); //readByte(in_b); } if(cRun + 999 < millis()){ cRun = millis(); if(WiFi.isConnected()){ led_wrk = !led_wrk; //digitalWrite(LED_WRK, led_wrk); nSampl++; } } } void connectToWifi() { Serial.println("Connecting to Wi-Fi..."); WiFi.begin(ssid, password); } void connectToMqtt() { Serial.println("Connecting to MQTT..."); //mqttClient.connect(); } void onWifiConnect(const WiFiEventStationModeGotIP& event) { Serial.println("Connected to Wi-Fi."); Serial.print("IP: "); Serial.println(WiFi.localIP()); connectToMqtt(); //digitalWrite(LED_WF, HIGH); } void onWifiDisconnect(const WiFiEventStationModeDisconnected& event) { Serial.println("Disconnected from Wi-Fi."); mqttReconnectTimer.detach(); // ensure we don't reconnect to MQTT while reconnecting to Wi-Fi wifiReconnectTimer.once(2, connectToWifi); //digitalWrite(LED_WF, LOW); } void onMqttConnect(bool sessionPresent) { Serial.println("Connected to MQTT."); Serial.print("Session present: "); Serial.println(sessionPresent); mqttClient.subscribe("/home/midroom/curtpos_set", 0); //digitalWrite(LED_MQ, HIGH); } void onMqttDisconnect(AsyncMqttClientDisconnectReason reason) { //Serial.println("Disconnected from MQTT."); if (WiFi.isConnected()) { mqttReconnectTimer.once(2, connectToMqtt); } //digitalWrite(LED_MQ, LOW); } void onMqttSubscribe(uint16_t packetId, uint8_t qos) { Serial.println("Subscribe acknowledged."); Serial.print(" packetId: "); Serial.println(packetId); Serial.print(" qos: "); Serial.println(qos); } void onMqttMessage(char* topic, char* payload, AsyncMqttClientMessageProperties properties, size_t len, size_t index, size_t total) { if(strcmp("/home/midroom/curtcmd", topic) == 0){ crc = 0; switch(atoi(payload)){ case 1: writeHex(TUYA_CLOSE); writeByte(crc); break; case 2: writeHex(TUYA_OPEN); writeByte(crc); break; case 3: writeHex(TUYA_STOP); writeByte(crc); break; } mqttClient.publish("/home/midroom/curtcmd", 0, false, "0"); } else if(strcmp("/home/midroom/curtpos_set", topic) == 0){ int pos = atoi(payload); crc = 0; if(pos == 100){ writeHex(TUYA_CLOSE); writeByte(crc); } else if(pos == 0){ writeHex(TUYA_OPEN); writeByte(crc); } else if (pos > 0 && pos < 100){ writeHex(TUYA_SET_POSITION); writeByte(100 - pos); writeByte(crc); } } } void readByte(uint8_t data) { if ((offset == 0 && data == 0x55) || (offset == 1 && data == 0xAA) || offset) { buffer[offset++] = data; if (offset > 6) { int len = buffer[4] << 8 | buffer[5]; if (7 + len == offset) { uint8_t crc = buffer[offset - 1]; uint8_t sum = 0; for (int i = 0; i < offset - 1; i++) sum += buffer[i]; if (sum == crc) { uint8_t cmd_type = buffer[3]; uint8_t data_id = buffer[6]; //uint8_t data_size = buffer[9]; // only 1byte or 4bytes values switch (cmd_type) { case 0x07: { switch (data_id) { // Motor reversing state case 0x67: { reversed = !!buffer[10]; break; } // Operation mode state case 0x66: { switch (buffer[10]) { case 0x00: cur_operation = CURT_CLOSING; break; case 0x02: cur_operation = CURT_IDLE; break; case 0x01: cur_operation = CURT_OPENING; break; } break; } // Position report during operation // Max value is 0x64 so the last byte is good enough case 0x68: { position = buffer[13] / 100.0f; curtOpened = !!position; break; } // Position report after operation case 0x65: { position = 1 - (buffer[13] / 100.0f); if (position > 0.95) position = 1; if (position < 0.05) position = 0; curtOpened = !!position; cur_operation = CURT_IDLE; break; } } Serial.println(); Serial.println(cur_operation); //publish_state(); break; } } } offset = 0; } } } } void writeByte(uint8_t data) { softSer.write(data); crc += data; } void writeHex(std::string data) { uint16_t i = 0; while (i < data.length()) { const char hex[2] = {data[i++], data[i++]}; uint8_t d = strtoul(hex, NULL, 16); writeByte(d); } }