ESPKit/sources/DOS/wset.c
2024-07-12 16:04:26 +03:00

653 lines
15 KiB
C

/*
=====================================================
ESP Setup program for Sprinter-WiFi ISA Card
Author: Roman A. Boykov
License: BSD 3-Clause
=====================================================
*/
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <string.h>
#include "esplib.h"
#include "wset.h"
char* set_speed = "AT+UART_CUR=115200,8,1,0,3\r\n\0";
char* echo_off = "ATE0\r\n\0";
char* station_mode = "AT+CWMODE=1\r\n\0";
char* no_sleep = "AT+SLEEP=0\r\n\0";
char* check_conn_ap_cmd = "AT+CWJAP?\r\n\0";
char* cwlap_opt = "AT+CWLAPOPT=1,23\r\n\0";
char* get_ap_list_cmd = "AT+CWLAP\r\n\0";
char* get_dhcp_cmd = "AT+CWDHCP?\r\n\0";
char* set_dhcp_cmd = "AT+CWDHCP=1,1\r\n\0";
char* get_ip_cmd = "AT+CIPSTA?\r\n\0";
char* cmd_end = "\r\n\0";
char rs_buff[RS_BUFF_SIZE];
/*
Encription mode names
*/
char* ecn[] = {"Open", "WEP", "WPA_PSK", "WPA2_PSK", "WPA_WPA2_PSK",
"WPA2_ENTERPRISE", "WPA3_PSK", "WPA2_WPA3_PSK"};
/*
Cause of connection errors
*/
char* conn_fault[] = {"None", "Connection timeout", "Wrong password",
"Can not find network", "Connection failed"};
void init_console()
{
clrscr();
}
/*
Init basic parameters of ESP
*/
void init_esp(void) {
#ifdef DEBUG
printf("Echo off");
#endif
uart_tx_cmd(echo_off, NULL, 0, 100);
#ifdef DEBUG
printf("Station mode");
#endif
uart_tx_cmd(station_mode, NULL, 0, 100);
#ifdef DEBUG
printf("No sleep");
#endif
uart_tx_cmd(no_sleep, NULL, 0, 100);
#ifdef DEBUG
printf("Setup uart");
#endif
uart_tx_cmd(set_speed, NULL, 0, 500);
#ifdef DEBUG
printf("Setup options");
#endif
uart_tx_cmd(cwlap_opt, NULL, 0, 100);
}
/*
Check connection to AP
Input:
ssid - pointer to buffer for Network ID
size - size of ssid buffer
Output:
RESULT_CONNECTED - if Ok
ssid - ID of network with which connection established
RESULT_NOT_CONNECTED - if no connections
*/
char esp_check_conn_ap(char* ssid, int size)
{
char *eol, *eos;
char res;
int len;
res = uart_tx_cmd(check_conn_ap_cmd, rs_buff, RS_BUFF_SIZE, 2000);
if (res == RESULT_OK) {
eol = (char *) strchr(rs_buff, LF);
if (eol) {
len = eol - rs_buff;
if (len>8 && strncmp("+CWJAP:\"", rs_buff,8) == 0) {
res = RESULT_CONNECTED;
if (ssid != NULL) {
eos = (char *) strchr(rs_buff+8, '"');
if (eos) {
len = eos-rs_buff-8;
if (len > (size-1)) {
len = size-1;
}
strncpy(ssid, rs_buff+8, len);
*(ssid+len) = 0;
}
}
} else {
if (strncmp("No AP",rs_buff,5) == 0) {
res = RESULT_NOT_CONNECTED;
} else {
printf("Unknown ESP response:\n%s\n", rs_buff);
res = RESULT_ERROR;
}
}
} else {
res = RESULT_NOT_CONNECTED;
}
}
return res;
}
/*
Parse info about Access Point
Input:
buff - pointer to line in response with info about AP
item - pointer to structure with info about AP
Output:
RESULT_OK - if parsing complete without errors
item - pointer with filled info about AP
*/
char parse_ap_info(char *buff, struct ap_info *item)
{
int res;
char *bol, *eol; // pointers to begin and end of line fragment
bol = buff;
eol = (char *) strchr(bol, ',');
if (eol != NULL) {
*eol = 0;
item->ecn = atoi(bol);
bol = eol+2;
eol = (char *) strchr(bol, '"');
if (eol != NULL) {
*eol = 0;
item->ssid = bol;
bol = eol+2;
eol = (char *) strchr(bol, ',');
if (eol) {
*eol = 0;
item->rssi = atoi(bol);
res = RESULT_OK;
} else {
res = RESULT_ERROR;
}
} else {
res = RESULT_ERROR;
}
} else {
res = RESULT_ERROR;
}
return res;
}
/*
Get list of Access Points (Wireless networks)
Input:
ap_list - array to put info about AP
size - size of array ap_list
Output:
ap_list - array with AP
result_size - number of found AP in ap_list
*/
char esp_get_ap_list(struct ap_info ap_list[], int size, int *result_size)
{
char *bol, *eol, *buff;
char res;
int ctr;
ctr = 0;
res = uart_tx_cmd(get_ap_list_cmd, rs_buff, RS_BUFF_SIZE, 5000);
if (res == RESULT_OK) {
buff = rs_buff;
while (buff < rs_buff + RS_BUFF_SIZE && ctr < size) {
// search begin of response line
bol = (char *) strstr(buff, "+CWLAP:(");
if (bol) {
// search end of response line
eol = (char *) strchr(buff, LF);
if (eol) {
*eol = 0; // mark end of line
buff = eol+1;
if ( parse_ap_info(bol+8, &ap_list[ctr]) != RESULT_OK ) {
printf("Can not parse AP Item!\n%s\n", bol+8);
break;
} else {
ctr++;
}
} else {
buff += 8;
}
} else {
break;
}
}
*result_size = ctr;
}
return res;
}
/*
Try to connect to specified Wireles network
Input:
ssid - Network identifier
passwd - password to use
Output:
RESULT_OK - if all Ok
RESULT_FAIL - if error and message with details displayed
*/
char connect_network(char *ssid, char *passwd) {
char *resp, *cmd, *bol, *eol;
char res, code;
resp = (char *)malloc(512);
cmd = (char *)malloc(512);
if (resp == NULL || cmd == NULL) {
printf("CN Out of memory!\n");
exit(1);
}
strset(cmd, 0);
sprintf(cmd, "AT+CWJAP=\"%s\",\"%s\"", ssid, passwd);
cmd = strcat(cmd, cmd_end);
res = uart_tx_cmd(cmd, resp, 512, 1000);
if (res != RESULT_OK) {
if (res == RESULT_FAIL) {
bol = (char *) strstr(resp, "+CWJAP:");
if (bol) {
bol += 7;
eol = (char *) strchr(bol, LF);
if (eol) {
*eol = 0;
code = atoi(bol);
if (code>0 && code<5) {
printf("%s", conn_fault[code]);
} else {
printf("Unknown error code: %d; '%s'", code, bol);
}
} else {
printf("no EOL\n");
}
} else {
printf("no +cwjap\n %s", resp);
}
}
}
free(resp);
free(cmd);
return res;
}
/*
Output main menu to select user action
*/
char select_main_menu(void)
{
char select;
printf("\n1 - Select WiFi Network\n");
printf("2 - Configure IP parameters\n");
printf("3 - Display info\n0 - Exit\n");
while (1) {
printf("\nEnter number 0..3: ");
scanf("%1d", &select);
fflush(stdin);
if (select >= 0 && select < 4) {
break;
}
}
return select;
}
/*
Output list of available Wireles networks.
Try to connect to network if required by user.
*/
void select_network(void)
{
char *passwd, yn, res;
int ap_list_size, ctr, select;
struct ap_info ap_list[AP_LIST_SIZE];
passwd = (char *)malloc(21);
if (passwd == NULL) {
printf("SN Out of memory!");
exit(1);
}
while (1) {
#ifdef DEBUG
printf("Get Network List");
#endif
esp_get_ap_list(ap_list, AP_LIST_SIZE, &ap_list_size);
printf("Select Wireless network to connect: \n\n");
for (ctr = 0; ctr< ap_list_size; ctr++) {
printf("%d - %s, %ddBm, %s\n",ctr+1, ap_list[ctr].ssid,
ap_list[ctr].rssi, ecn[ap_list[ctr].ecn]);
}
while (1) {
printf("\nEnter number 1..%d or 0 to exit: ", ap_list_size);
scanf("%2d", &select);
fflush(stdin);
if (select >= 0 && select <= ap_list_size) {
break;
}
}
if (select == 0) {
break;
}
select--;
printf("Enter password for %s: ", ap_list[select].ssid);
scanf("%20s", passwd);
fflush(stdin);
printf("Connecting to Network %s: ", ap_list[select].ssid);
res = connect_network(ap_list[select].ssid, passwd);
if (res != RESULT_OK) {
printf("\nTry again Y|n?", ap_list[select].ssid);
scanf("%c",&yn);
fflush(stdin);
if (yn == 'N' || yn == 'n') {
break;
}
} else {
break;
}
}
free(passwd);
}
/*
Get info about AP with which communication is established
*/
void get_current_ap(void)
{
char found, *ssid;
ssid = (char *)malloc(128);
if (ssid != NULL) {
#ifdef DEBUG
printf("Get WiFi Network");
#endif
found = esp_check_conn_ap(ssid, 128);
if (found == RESULT_CONNECTED) {
printf("Connected to Wireles net: %s\n", ssid);
} else if (found == RESULT_NOT_CONNECTED) {
printf("Not connected to Wireles net!\n");
} else {
printf("CAP Unexpected error: %d\n", found);
exit(1);
}
free(ssid);
} else {
printf("CAP Out of memory!");
exit(1);
}
}
char set_dhcp_mode(void)
{
#ifdef DEBUG
printf("Set DHCP mode");
#endif
return uart_tx_cmd(set_dhcp_cmd, rs_buff, RS_BUFF_SIZE, 1000);
}
char is_byte(char *byte)
{
int i;
i = atoi(byte);
return (i >= 0 && i <= 255);
}
#define ADDR_LENGTH 16
/*
Check string to looks like IP address
Input:
ip_str - pointer to string with IP
Output:
1 - look like IP
0 - not
*/
char is_ip_addr(char *ip_str)
{
char *p1, *p2, *p3, *ip;
char res;
res = 0;
if (strlen(ip_str) < ADDR_LENGTH) {
ip = malloc(ADDR_LENGTH);
if (ip == NULL) {
printf("IIP Out of memory!\n");
exit(1);
}
strcpy(ip, ip_str);
p1 = (char *) strchr(ip, '.');
if (p1) {
p2 = (char *) strchr(p1+1, '.');
if (p2) {
p3 = (char *) strchr(p2+1, '.');
if (p3) {
*p1 = 0;
*p2 = 0;
*p3 = 0;
res = (is_byte(ip) && is_byte(p1+1) &&
is_byte(p2+1) && is_byte(p3+1));
}
}
}
free(ip);
}
return res;
}
void enter_ip(char *message, char *ip)
{
char is_ip;
do {
printf("Enter %s: ", message);
scanf("%15s", ip);
fflush(stdin);
is_ip = is_ip_addr(ip);
if (!is_ip) {
printf("Invalid address, not in nnn.nnn.nnn.nnn format! Where nnn=0..255\n");
}
} while (!is_ip);
}
char set_ip_config(char *ip, char *gateway, char *netmask)
{
char res, *resp, *cmd;
resp = (char *)malloc(512);
cmd = (char *)malloc(256);
if (resp == NULL || cmd == NULL) {
printf("SIP Out of memory!\n");
exit(1);
}
strset(cmd, 0);
sprintf(cmd, "AT+CIPSTA=\"%s\",\"%s\",\"%s\"", ip, gateway, netmask);
cmd = strcat(cmd, cmd_end);
#ifdef DEBUG
printf("Set ip config");
#endif
res = uart_tx_cmd(cmd, resp, 512, 2000);
if (res != RESULT_OK) {
/*
if (res == RESULT_FAIL) {
bol = (char *) strstr(resp, "+CWJAP:");
if (bol) {
}
}
*/
}
free(cmd);
free(resp);
return res;
}
/*
Allow the user to select DHCP or manual IP-configuration
*/
void config_ip(void)
{
char select, *ip, *netmask, *gateway;
ip = malloc(ADDR_LENGTH);
netmask = malloc(ADDR_LENGTH);
gateway = malloc(ADDR_LENGTH);
if (ip == NULL || netmask == NULL || gateway == NULL) {
printf("CIP Out of memory!\n");
exit(1);
}
strnset(ip,0,ADDR_LENGTH);
strnset(netmask,0,ADDR_LENGTH);
strnset(gateway,0,ADDR_LENGTH);
printf("Select mode:\n1 - Automatic via DHCP\n");
printf("2 - Specify IP-address, netmask and gateway\n0 - Exit.\n");
while (1) {
printf("\nEnter number 0..2: ");
scanf("%1d", &select);
fflush(stdin);
if (select >= 0 && select < 3) {
break;
}
}
switch (select) {
case 1 : {
set_dhcp_mode();
break;
}
case 2 : {
enter_ip("IP-address", ip);
enter_ip("Gateway", gateway);
enter_ip("Net mask", netmask);
set_ip_config(ip, gateway, netmask);
break;
}
}
free(ip);
free(gateway);
free(netmask);
}
/*
Get state of DHCP
Output:
RESULT_ENABLED - if DHCP enabled
RESULT_DISABLED - DHCP is disabled
*/
char get_dhcp_state(void) {
char *bol, *eol, res;
#ifdef DEBUG
printf("Get DHCP info");
#endif
res = uart_tx_cmd(get_dhcp_cmd, rs_buff, RS_BUFF_SIZE, 1000);
if (res == RESULT_OK) {
bol = (char *) strstr(rs_buff, "+CWDHCP:");
if (bol) {
bol += 8;
eol = (char *) strchr(bol, LF);
if (eol) {
*eol = 0;
if (atoi(bol) & 0x02) { // for new AT versions, it is changed to 0x01
printf("DHCP enabled\n");
res = RESULT_ENABLED;
} else {
printf("DHCP disabled\n");
res = RESULT_DISABLED;
}
}
} else {
printf("No +CWDHCP!\n %s", rs_buff);
}
}
return res;
}
/*
Display configurtion of IP adresses
*/
void get_ip_config(void)
{
char *bol, *eol, *name, res, ctr;
#ifdef DEBUG
printf("Get IP config");
#endif
res = uart_tx_cmd(get_ip_cmd, rs_buff, RS_BUFF_SIZE, 1000);
bol = rs_buff;
if (res == RESULT_OK) {
ctr = 0;
while (ctr++ < 4) {
bol = (char *) strstr(bol, "+CIPSTA:");
if (bol) {
bol += 8;
eol = (char *) strchr(bol, ':');
if (eol) {
*eol = 0;
name = bol;
bol = eol+1;
eol = (char *) strchr(bol, LF);
if (eol) {
*eol = 0;
printf("%s: %s\n", name, bol);
}
bol = eol+1;
}
} else {
break;
}
}
}
}
/*
Display currenf Info, configured in ESP
*/
void display_info(void)
{
printf("\n--- Current info ---\n");
get_current_ap();
get_dhcp_state();
get_ip_config();
printf("\n--------------------\n");
}
/*
--------------------------------------------------------------------------
*/
void main()
{
char found;
clrscr();
printf(MSG_START);
found = isa_init();
if (!found) {
printf(MSG_NOT_FOUND);
exit(EXIT_FAILURE);
}
printf(MSG_FOUND, isa_get_slot());
uart_init();
esp_reset(1);
init_esp();
while (1) {
switch(select_main_menu()) {
case 1: {
select_network();
break;
}
case 2: {
config_ip();
break;
}
case 3: {
display_info();
break;
}
default: {
printf("Bye!\n");
exit(0);
}
}
}
}