Open Mantikor opened 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.
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.
@NonPIayerCharacter : Thats great. It would be nice if you could share your solution to other guys.
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);
}
}
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!