MeterLogger
cgiwifi.c
Go to the documentation of this file.
1 /*
2 Cgi/template routines for the /wifi url.
3 */
4 
5 /*
6  * ----------------------------------------------------------------------------
7  * "THE BEER-WARE LICENSE" (Revision 42):
8  * Jeroen Domburg <jeroen@spritesmods.com> wrote this file. As long as you retain
9  * this notice you can do whatever you want with this stuff. If we meet some day,
10  * and you think this stuff is worth it, you can buy me a beer in return.
11  * ----------------------------------------------------------------------------
12  */
13 
14 
15 #include <esp8266.h>
16 #include "httpd.h"
17 #include "config.h"
18 #include "debug.h"
19 
20 #include "utils.h"
21 #include "tinyprintf.h"
22 
23 //Enable this to disallow any changes in AP settings
24 //#define DEMO_MODE
25 
26 //WiFi access point data
27 typedef struct {
28  char ssid[32];
29  char rssi;
30  char enc;
31 } ApData;
32 
33 //Scan result
34 typedef struct {
35  char scanInProgress; //if 1, don't access the underlying stuff from the webpage.
37  int noAps;
39 
40 //Static scan status storage.
42 
44 
45 //Callback the code calls when a wlan ap scan is done. Basically stores the result in
46 //the cgiWifiAps struct.
47 void ICACHE_FLASH_ATTR wifiScanDoneCb(void *arg, STATUS status) {
48  int n;
49  struct bss_info *bss_link = (struct bss_info *)arg;
50  INFO("wifiScanDoneCb %d\n", status);
51  if (status!=OK) {
52  cgiWifiAps.scanInProgress=0;
53  return;
54  }
55 
56  //Clear prev ap data if needed.
57  if (cgiWifiAps.apData!=NULL) {
58  for (n=0; n<cgiWifiAps.noAps; n++) os_free(cgiWifiAps.apData[n]);
59  os_free(cgiWifiAps.apData);
60  }
61 
62  //Count amount of access points found.
63  n=0;
64  while (bss_link != NULL) {
65  bss_link = bss_link->next.stqe_next;
66  n++;
67  }
68  //Allocate memory for access point data
69  cgiWifiAps.apData=(ApData **)os_malloc(sizeof(ApData *)*n);
70  cgiWifiAps.noAps=n;
71  INFO("Scan done: found %d APs\n", n);
72 
73  //Copy access point data to the static struct
74  n=0;
75  bss_link = (struct bss_info *)arg;
76  while (bss_link != NULL) {
77  if (n>=cgiWifiAps.noAps) {
78  //This means the bss_link changed under our nose. Shouldn't happen!
79  //Break because otherwise we will write in unallocated memory.
80  INFO("Huh? I have more than the allocated %d aps!\n", cgiWifiAps.noAps);
81  break;
82  }
83  //Save the ap data.
84  cgiWifiAps.apData[n]=(ApData *)os_malloc(sizeof(ApData));
85  cgiWifiAps.apData[n]->rssi=bss_link->rssi;
86  cgiWifiAps.apData[n]->enc=bss_link->authmode;
87  strncpy(cgiWifiAps.apData[n]->ssid, (char*)bss_link->ssid, 32);
88 
89  bss_link = bss_link->next.stqe_next;
90  n++;
91  }
92  //We're done.
93  cgiWifiAps.scanInProgress=0;
94 }
95 
96 
97 //Routine to start a WiFi access point scan.
99 // int x;
100  if (cgiWifiAps.scanInProgress) return;
101  cgiWifiAps.scanInProgress=1;
103 }
104 
105 //This CGI is called from the bit of AJAX-code in wifi.tpl. It will initiate a
106 //scan for access points and if available will return the result of an earlier scan.
107 //The result is embedded in a bit of JSON parsed by the javascript in wifi.tpl.
109  int len;
110  int i;
111  char buff[1024];
112  httpdStartResponse(connData, 200);
113  httpdHeader(connData, "Content-Type", "text/json");
114  httpdEndHeaders(connData);
115 
116  if (cgiWifiAps.scanInProgress==1) {
117  //We're still scanning. Tell Javascript code that.
118  tfp_snprintf(buff, 1024, "{\n \"result\": { \n\"inProgress\": \"1\"\n }\n}\n");
119  len = strlen(buff);
120  httpdSend(connData, buff, len);
121  } else {
122  //We have a scan result. Pass it on.
123  tfp_snprintf(buff, 1024, "{\n \"result\": { \n\"inProgress\": \"0\", \n\"APs\": [\n");
124  len = strlen(buff);
125  httpdSend(connData, buff, len);
126  if (cgiWifiAps.apData==NULL) cgiWifiAps.noAps=0;
127  for (i=0; i<cgiWifiAps.noAps; i++) {
128  //Fill in json code for an access point
129  tfp_snprintf(buff, 1024, "{\"essid\": \"%s\", \"rssi\": \"%d\", \"enc\": \"%d\"}%s\n",
130  cgiWifiAps.apData[i]->ssid, cgiWifiAps.apData[i]->rssi,
131  cgiWifiAps.apData[i]->enc, (i==cgiWifiAps.noAps-1)?"":",");
132  len = strlen(buff);
133  httpdSend(connData, buff, len);
134  }
135  tfp_snprintf(buff, 1024, "]\n}\n}\n");
136  len = strlen(buff);
137  httpdSend(connData, buff, len);
138  //Also start a new scan.
139  wifiStartScan();
140  }
141  return HTTPD_CGI_DONE;
142 }
143 
144 //Temp store for new ap info.
145 //static struct station_config stconf;
146 
147 
148 //This routine is ran some time after a connection attempt to an access point. If
149 //the connect succeeds, this gets the module in STA-only mode.
150 static void ICACHE_FLASH_ATTR resetTimerCb(void *arg) {
151 // int x=wifi_station_get_connect_status();
152 // if (x==STATION_GOT_IP) {
153 // //Go to STA mode. This needs a reset, so do that.
154 // INFO("Got IP. Going into STA mode..\n");
155 #ifdef DEBUG
156  os_printf("restarting...\n");
157 #endif
158 // wifi_set_opmode(1);
159  system_restart();
160 // } else {
161 // INFO("Connect fail. Not going into STA-only mode.\n");
162 // //Maybe also pass this through on the webpage?
163 // }
164 }
165 
166 //This cgi uses the routines above to connect to a specific access point with the
167 //given ESSID using the given password.
169  char essid[128];
170  char passwd[128];
171 #ifdef IMPULSE
172  char impulse_meter_serial[32 + 1];
173  char impulse_meter_energy_kw[32 + 1];
174  char impulse_meter_energy[32 + 1];
175  char impulses_per_kwh[8 + 1];
176 #endif
177 
178  if (connData->conn==NULL) {
179  //Connection aborted. Clean up.
180  return HTTPD_CGI_DONE;
181  }
182 
183  httpdFindArg(connData->postBuff, "essid", essid, sizeof(essid));
184  httpdFindArg(connData->postBuff, "passwd", passwd, sizeof(passwd));
185 #ifdef IMPULSE
186  httpdFindArg(connData->postBuff, "impulse_meter_serial", impulse_meter_serial, sizeof(impulse_meter_serial));
187  httpdFindArg(connData->postBuff, "impulse_meter_energy", impulse_meter_energy_kw, sizeof(impulse_meter_energy_kw));
188  httpdFindArg(connData->postBuff, "impulses_per_kwh", impulses_per_kwh, sizeof(impulses_per_kwh));
189 #endif
190 
191  os_strncpy((char*)sys_cfg.sta_ssid, essid, 32);
192  os_strncpy((char*)sys_cfg.sta_pwd, passwd, 64);
193 #ifdef IMPULSE
194  os_strncpy((char*)sys_cfg.impulse_meter_serial, impulse_meter_serial, 32 + 1);
195  kw_to_w_str(impulse_meter_energy_kw, impulse_meter_energy);
196  os_strncpy((char*)sys_cfg.impulse_meter_energy, impulse_meter_energy, 32 + 1);
197  os_strncpy((char*)sys_cfg.impulses_per_kwh, impulses_per_kwh, 8 + 1);
198  sys_cfg.impulse_meter_count = 0;
199 #endif
200 
201  cfg_save();
202 
203  INFO("Try to connect to AP %s pw %s\n", essid, passwd);
204 
205  //Schedule disconnect/connect
208  os_timer_arm(&resetTimer, 1000, 0);
209 #ifdef IMPULSE
210  httpdRedirect(connData, "impulse_meter_setting_up.html");
211 #else
212  httpdRedirect(connData, "setting_up.html");
213 #endif
214 
215  // restart to go directly to sample mode after 5 seconds
218  os_timer_arm(&resetTimer, 5000, 0);
219 
220  return HTTPD_CGI_DONE;
221 }
222 
223 //This cgi uses the routines above to connect to a specific access point with the
224 //given ESSID using the given password.
226  int len;
227  char buff[1024];
228 
229  if (connData->conn==NULL) {
230  //Connection aborted. Clean up.
231  return HTTPD_CGI_DONE;
232  }
233 
234  len=httpdFindArg(connData->getArgs, "mode", buff, sizeof(buff));
235  if (len!=0) {
236  INFO("cgiWifiSetMode: %s\n", buff);
237 #ifndef DEMO_MODE
238  wifi_set_opmode(atoi(buff));
239  system_restart();
240 #endif
241  }
242  httpdRedirect(connData, "/wifi");
243  return HTTPD_CGI_DONE;
244 }
245 
246 //Template code for the WLAN page.
247 void ICACHE_FLASH_ATTR tplSetup(HttpdConnData *connData, char *token, void **arg) {
248  char buff[1024];
249 #ifdef IMPULSE
250  char impulse_meter_energy[32 + 1];
251 #endif // IMPULSE
252  int x;
253  //static struct station_config stconf;
254  if (token==NULL) return;
255  //wifi_station_get_config(&stconf);
256  cfg_load();
257 
258  os_strcpy(buff, "Unknown");
259  if (os_strcmp(token, "WiFiMode")==0) {
260  x=wifi_get_opmode();
261  if (x == 1) os_strcpy(buff, "Client");
262  if (x == 2) os_strcpy(buff, "SoftAP");
263  if (x == 3) os_strcpy(buff, "STA+AP");
264  }
265  else if (os_strcmp(token, "currSsid") == 0) {
266  os_strcpy(buff, (char*)sys_cfg.sta_ssid);
267  }
268  else if (os_strcmp(token, "WiFiPasswd") == 0) {
269  os_strcpy(buff, (char*)sys_cfg.sta_pwd);
270  }
271  else if (os_strcmp(token, "WiFiapwarn") == 0) {
272  x = wifi_get_opmode();
273  if (x == 2) {
274  os_strcpy(buff, "<b>Can't scan in this mode.</b> Click <a href=\"setmode.cgi?mode=3\">here</a> to go to STA+AP mode.");
275  }
276  else {
277  os_strcpy(buff, "Click <a href=\"setmode.cgi?mode=2\">here</a> to go to standalone AP mode.");
278  }
279  }
280 #ifdef IMPULSE
281  else if (os_strcmp(token, "ImpulseMeterSerial") == 0) {
282  os_strcpy(buff, (char*)sys_cfg.impulse_meter_serial);
283  }
284  else if (os_strcmp(token, "ImpulseMeterEnergy") == 0) {
285  tfp_snprintf(impulse_meter_energy, 32 + 1, "%u", atoi(sys_cfg.impulse_meter_energy) + sys_cfg.impulse_meter_count * (1000 / atoi(sys_cfg.impulses_per_kwh)));
286  w_to_kw_str(impulse_meter_energy, buff);
287  }
288  else if (os_strcmp(token, "ImpulsesPerKwh") == 0) {
289  os_strcpy(buff, (char*)sys_cfg.impulses_per_kwh);
290  }
291 #endif
292 
293  httpdSend(connData, buff, -1);
294 }
uint8_t sta_ssid[64]
Definition: config.h:48
#define os_timer_t
Definition: os_type.h:34
static void ICACHE_FLASH_ATTR wifiStartScan()
Definition: cgiwifi.c:98
#define os_timer_disarm
Definition: osapi.h:51
char * getArgs
Definition: httpd.h:22
void ICACHE_FLASH_ATTR tplSetup(HttpdConnData *connData, char *token, void **arg)
Definition: cgiwifi.c:247
AUTH_MODE authmode
uint8_t sta_pwd[64]
Definition: config.h:49
#define NULL
Definition: def.h:47
void ICACHE_FLASH_ATTR cfg_save()
Definition: config.c:28
ICACHE_FLASH_ATTR void kw_to_w_str(char *kw, char *w)
Definition: utils.c:67
ICACHE_FLASH_ATTR void w_to_kw_str(char *w, char *kw)
Definition: utils.c:54
ICACHE_FLASH_ATTR void httpdRedirect(HttpdConnData *conn, char *newUrl)
Definition: httpd.c:246
#define ICACHE_FLASH_ATTR
Definition: c_types.h:99
static os_timer_t resetTimer
Definition: cgiwifi.c:43
int ICACHE_FLASH_ATTR cgiSetup(HttpdConnData *connData)
Definition: cgiwifi.c:168
char rssi
Definition: cgiwifi.c:29
ApData ** apData
Definition: cgiwifi.c:36
void ICACHE_FLASH_ATTR wifiScanDoneCb(void *arg, STATUS status)
Definition: cgiwifi.c:47
#define os_printf
Definition: osapi.h:62
#define HTTPD_CGI_DONE
Definition: httpd.h:9
uint8 wifi_get_opmode(void)
#define os_timer_setfn
Definition: osapi.h:52
ScanResultData cgiWifiAps
Definition: cgiwifi.c:41
ICACHE_FLASH_ATTR int httpdFindArg(char *line, char *arg, char *buff, int buffLen)
Definition: httpd.c:167
#define os_strcmp
Definition: osapi.h:41
#define os_malloc(s)
Definition: mem.h:41
#define os_strncpy
Definition: osapi.h:45
char ssid[32]
Definition: cgiwifi.c:28
static void ICACHE_FLASH_ATTR resetTimerCb(void *arg)
Definition: cgiwifi.c:150
Definition: cgiwifi.c:27
int ICACHE_FLASH_ATTR cgiWiFiScan(HttpdConnData *connData)
Definition: cgiwifi.c:108
void system_restart(void)
STATUS
Definition: c_types.h:79
Definition: c_types.h:80
#define os_free(s)
Definition: mem.h:40
ICACHE_FLASH_ATTR void httpdStartResponse(HttpdConnData *conn, int code)
Definition: httpd.c:219
uint8 ssid[32]
char enc
Definition: cgiwifi.c:30
ICACHE_FLASH_ATTR void httpdEndHeaders(HttpdConnData *conn)
Definition: httpd.c:240
#define strncpy(a, b, c)
Definition: platform.h:16
ICACHE_FLASH_ATTR int tfp_snprintf(char *str, size_t size, const char *format,...)
Definition: tinyprintf.c:480
ICACHE_FLASH_ATTR void httpdHeader(HttpdConnData *conn, const char *field, const char *val)
Definition: httpd.c:229
int ICACHE_FLASH_ATTR cgiWifiSetMode(HttpdConnData *connData)
Definition: cgiwifi.c:225
bool wifi_station_scan(struct scan_config *config, scan_done_cb_t cb)
struct espconn * conn
Definition: httpd.h:20
#define os_timer_arm(a, b, c)
Definition: osapi.h:50
ICACHE_FLASH_ATTR int httpdSend(HttpdConnData *conn, const char *data, int len)
Definition: httpd.c:270
#define os_strcpy
Definition: osapi.h:42
void ICACHE_FLASH_ATTR cfg_load()
Definition: config.c:77
char * postBuff
Definition: httpd.h:28
static HttpdConnData connData[MAX_CONN]
Definition: httpd.c:63
#define INFO(...)
Definition: debug.h:17
char scanInProgress
Definition: cgiwifi.c:35
#define strlen(a)
Definition: platform.h:25
bool wifi_set_opmode(uint8 opmode)
syscfg_t sys_cfg
Definition: config.c:12