parasite85 / tuya_tygwzw1_hack

18 stars 6 forks source link

Backup & Realtek simple WLAN configuration #3

Open Mantikor opened 6 months ago

Mantikor commented 6 months ago

First of all, I would like to say THANK YOU for your work! Secondly, the question: it is possible to make a backup of the original firmware of Main module and Zigbee module? Third: is it possible to make firmware for the Wi-Fi module in order to enter data for the SSID through the Android/iOS application, as described in manual in point 2 solution 1: Device AP mode + Smartphone APP, and not enter SSID/password through the terminal. Thanx for answers!

parasite85 commented 6 months ago

Regarding backup: I have not tried possibility to backup original firmware. Regarding AP: I think it should be possible... but it will take much more time to develop. Right now i do not have much time for such activity. Maybe in future.

I propose to do different thing - use ESP32 and UART connection to zigbee module taken from gateway. You can do AP mode + simple http interface and it will even not require any additional app from smartphone.

NonPIayerCharacter commented 6 months ago

Its easier to build arduino sdk, and have builtin ssid&password. I used https://github.com/ambiot/amb1_arduino sdk, and 'ported' example_socket_tcp_trx_1.c. That worked for me, even though i get z2m restarts several times per day. Now i am waiting for realtek ameba (rtl8195a/rtl8711am) support in libretiny, and it will be much easier for me, as it will include ota and fallback ap, using which, i will be able to connect to ap using phone/laptop.

parasite85 commented 6 months ago

@NonPIayerCharacter : Thats great. It would be nice if you could share your solution to other guys.

NonPIayerCharacter commented 5 months ago

Not sure how stable it will be, i only tested it once, and z2m connected successfully. I just desoldered the main module, and soldered esp12f with wires, and installed esphome with esphome-stream-server component. Now it works excellently with ZHA.

#define PLATFORM_FREERTOS
#include <Adafruit_GPS.h>
#include <PMS3003.h>
#include "WiFi.h"
#include <SoftwareSerial.h>
#include "tcp.h"
#include <lwip/sockets.h>
#include "serial_api.h"

#define SERVER_PORT 80
#define LISTEN_QLEN 2
#undef memset
#undef read
#undef write
//#define UART_TX SERIAL_TX
//#define UART_RX SERIAL_RX

#define UART_TX 1
#define UART_RX 0
char ssid[] = "--";
char pass[] = "--";
int status = WL_IDLE_STATUS;
static int tx_exit = 0, rx_exit = 0;
SoftwareSerial mySerial(UART_RX, UART_TX);  // RX, TX
static SemaphoreHandle_t tcp_tx_rx_sema;
static SemaphoreHandle_t uart_tx_rx_sema;
TaskHandle_t maintask;

void setup() {
  if (uart_tx_rx_sema == NULL) {
    uart_tx_rx_sema = xSemaphoreCreateMutex();
    if ((uart_tx_rx_sema) != NULL) {
      xSemaphoreGive((uart_tx_rx_sema));
    }
  }
  mySerial.begin(115200, 8, PARITY_EVEN, 1, FLOW_CONTROL_RTSCTS, 0, 0);
  connect_to_wifi();
}

void loop() {
  if (WiFi.status() != WL_CONNECTED) {
    connect_to_wifi();
  }
  example_socket_tcp_trx_thread(NULL);
}

void uart_send_data(unsigned char *data, int count) {
  unsigned int i = 0;
  xSemaphoreTake(uart_tx_rx_sema, (TickType_t)64);
  for (i = 0; i < count; i++) {
    mySerial.print(data[i]);
  }
  xSemaphoreGive(uart_tx_rx_sema);
}

static void tx_thread(void *param) {
  int client_fd = *(int *)param;
  unsigned char buffer[1024];
  memset(buffer, 0, sizeof(buffer));
  Serial.print("\ntx_thread start\n");

  while (1) {
    int ret = 0;
    int i = 0;
    int j = 0;
    for (i = 0; i < sizeof(buffer); i++) {
      if (mySerial.available()) {
        xSemaphoreTake(uart_tx_rx_sema, (TickType_t)64);
        buffer[j++] = mySerial.read();
        xSemaphoreGive(uart_tx_rx_sema);
      }
    }

    if (j > 0) {
      if (j < sizeof(buffer)) {
        xSemaphoreTake(tcp_tx_rx_sema, (TickType_t)64);
        ret = send(client_fd, buffer, j, 0);
        xSemaphoreGive(tcp_tx_rx_sema);
      } else {
        Serial.print("buff corrupted");
      }
    } else {
      if (rx_exit) {
        goto exit;
      }
      continue;  // avoid quit
    }

    if (ret <= 0)
      goto exit;

    vTaskDelay(100);
  }

exit:
  Serial.print("\ntx_thread exit\n");
  tx_exit = 1;
  vTaskDelete(NULL);
}
static void rx_thread(void *param) {
  int client_fd = *(int *)param;
  unsigned char buffer[1024];
  Serial.print("\nrx_thread start\n");

  while (1) {
    int ret = 0, sock_err = 0;
    size_t err_len = sizeof(sock_err);

    xSemaphoreTake(tcp_tx_rx_sema, (TickType_t)64);
    ret = recv(client_fd, buffer, sizeof(buffer), MSG_DONTWAIT);
    getsockopt(client_fd, SOL_SOCKET, SO_ERROR, &sock_err, &err_len);
    xSemaphoreGive(tcp_tx_rx_sema);
    if (ret > 0) {
      uart_send_data(buffer, ret);
    }

    // ret == -1 and socket error == EAGAIN when no data received for nonblocking
    if ((ret == -1) && (sock_err == EAGAIN))
      continue;
    else if (ret <= 0)
      goto exit;

    vTaskDelay(10);
  }

exit:
  Serial.print("\nrx_thread exit\n");
  rx_exit = 1;
  vTaskDelete(NULL);
}

static void example_socket_tcp_trx_thread(void *param) {
  int server_fd = -1, client_fd = -1;
  struct sockaddr_in server_addr, client_addr;
  size_t client_addr_size;

  printf("\nExample: socket tx/rx 1\n");

  server_fd = socket(AF_INET, SOCK_STREAM, 0);
  server_addr.sin_family = AF_INET;
  server_addr.sin_port = htons(SERVER_PORT);
  server_addr.sin_addr.s_addr = INADDR_ANY;

  if (bind(server_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) != 0) {
    printf("ERROR: bind\n");
    goto exit;
  }

  if (listen(server_fd, LISTEN_QLEN) != 0) {
    printf("ERROR: listen\n");
    goto exit;
  }

  while (1) {
    client_addr_size = sizeof(client_addr);
    client_fd = accept(server_fd, (struct sockaddr *)&client_addr, &client_addr_size);

    if (client_fd >= 0) {
      tx_exit = 1;
      rx_exit = 1;
      if (tcp_tx_rx_sema == NULL) {
        tcp_tx_rx_sema = xSemaphoreCreateMutex();
      }

      if (xTaskCreate(tx_thread, ((const char *)"tx_thread"), 512, &client_fd, tskIDLE_PRIORITY + 1, NULL) != pdPASS)
        printf("\n\rexample_socket_tcp_trx_thread xTaskCreate(tx_thread) failed");
      else
        tx_exit = 0;

      vTaskDelay(10);

      if (xTaskCreate(rx_thread, ((const char *)"rx_thread"), 512, &client_fd, tskIDLE_PRIORITY + 1, NULL) != pdPASS)
        printf("\n\rexample_socket_tcp_trx_thread xTaskCreate(rx_thread) failed");
      else
        rx_exit = 0;

      while (1) {
        if (tx_exit && rx_exit) {
          close(client_fd);
          break;
        } else
          vTaskDelay(1000);
      }

      if ((tcp_tx_rx_sema) != NULL) {
        xSemaphoreGive((tcp_tx_rx_sema));
      }
    }
  }

exit:
  close(server_fd);
}

void connect_to_wifi() {
  WiFi.disconnect();
  delay(100);

  while (WiFi.begin(ssid, pass) != WL_CONNECTED) {
    delay(5000);
  }
}