├── .gitignore ├── Makefile ├── README.md ├── doc ├── blackbox_closed.png ├── blackbox_open.png └── usb.png └── user ├── base64.c ├── base64.h ├── data.h ├── fifo.h ├── scanmap.c ├── scanmap.h ├── sync.c ├── sync.h ├── uart.c ├── uart.h ├── uart_register.h ├── upg.c ├── upg.h ├── user_config.h ├── user_json.c ├── user_json.h ├── user_main.c └── wifis_spots.h /.gitignore: -------------------------------------------------------------------------------- 1 | *.bin 2 | user/wifis_spots.h 3 | user/user_config.h 4 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for ESP8266 projects 2 | # 3 | # Thanks to: 4 | # - zarya 5 | # - Jeroen Domburg (Sprite_tm) 6 | # - Christian Klippel (mamalala) 7 | # - Tommie Gannert (tommie) 8 | # 9 | # Changelog: 10 | # - 2014-10-06: Changed the variables to include the header file directory 11 | # - 2014-10-06: Added global var for the Xtensa tool root 12 | # - 2014-11-23: Updated for SDK 0.9.3 13 | # - 2014-12-25: Replaced esptool by esptool.py 14 | 15 | # Output directors to store intermediate compiled files 16 | # relative to the project directory 17 | BUILD_BASE = build 18 | FW_BASE = firmware 19 | 20 | # base directory for the compiler 21 | XTENSA_TOOLS_ROOT ?= /opt/Espressif/crosstool-NG/builds/xtensa-lx106-elf/bin 22 | 23 | # base directory of the ESP8266 SDK package, absolute 24 | SDK_BASE ?= /opt/Espressif/ESP8266_SDK 25 | 26 | # esptool.py path and port 27 | ESPTOOL ?= esptool.py 28 | ESPPORT ?= /dev/ttyUSB0 29 | 30 | # name for the target project 31 | TARGET = app 32 | 33 | # which modules (subdirectories) of the project to include in compiling 34 | MODULES = driver user 35 | EXTRA_INCDIR = include 36 | 37 | # libraries used in this project, mainly provided by the SDK 38 | LIBS = c gcc hal pp phy net80211 lwip wpa main ssl upgrade 39 | 40 | # compiler flags using during compilation of source files 41 | CFLAGS = -Os -g -O2 -Wpointer-arith -Wundef -Werror -Wl,-EL -fno-inline-functions -nostdlib -mlongcalls -mtext-section-literals -D__ets__ -DICACHE_FLASH 42 | 43 | # linker flags used to generate the main object file 44 | LDFLAGS = -nostdlib -Wl,--no-check-sections -u call_user_start -Wl,-static 45 | 46 | # linker script used for the above linkier step 47 | LD_SCRIPT = eagle.app.v6.ld 48 | 49 | # various paths from the SDK used in this project 50 | SDK_LIBDIR = lib 51 | SDK_LDDIR = ld 52 | SDK_INCDIR = include include/json 53 | 54 | # we create two different files for uploading into the flash 55 | # these are the names and options to generate them 56 | FW_FILE_1_ADDR = 0x00000 57 | FW_FILE_2_ADDR = 0x40000 58 | 59 | # select which tools to use as compiler, librarian and linker 60 | CC := $(XTENSA_TOOLS_ROOT)/xtensa-lx106-elf-gcc 61 | AR := $(XTENSA_TOOLS_ROOT)/xtensa-lx106-elf-ar 62 | LD := $(XTENSA_TOOLS_ROOT)/xtensa-lx106-elf-gcc 63 | 64 | 65 | 66 | #### 67 | #### no user configurable options below here 68 | #### 69 | SRC_DIR := $(MODULES) 70 | BUILD_DIR := $(addprefix $(BUILD_BASE)/,$(MODULES)) 71 | 72 | SDK_LIBDIR := $(addprefix $(SDK_BASE)/,$(SDK_LIBDIR)) 73 | SDK_INCDIR := $(addprefix -I$(SDK_BASE)/,$(SDK_INCDIR)) 74 | 75 | SRC := $(foreach sdir,$(SRC_DIR),$(wildcard $(sdir)/*.c)) 76 | OBJ := $(patsubst %.c,$(BUILD_BASE)/%.o,$(SRC)) 77 | LIBS := $(addprefix -l,$(LIBS)) 78 | APP_AR := $(addprefix $(BUILD_BASE)/,$(TARGET)_app.a) 79 | TARGET_OUT := $(addprefix $(BUILD_BASE)/,$(TARGET).out) 80 | 81 | LD_SCRIPT := $(addprefix -T$(SDK_BASE)/$(SDK_LDDIR)/,$(LD_SCRIPT)) 82 | 83 | INCDIR := $(addprefix -I,$(SRC_DIR)) 84 | EXTRA_INCDIR := $(addprefix -I,$(EXTRA_INCDIR)) 85 | MODULE_INCDIR := $(addsuffix /include,$(INCDIR)) 86 | 87 | FW_FILE_1 := $(addprefix $(FW_BASE)/,$(FW_FILE_1_ADDR).bin) 88 | FW_FILE_2 := $(addprefix $(FW_BASE)/,$(FW_FILE_2_ADDR).bin) 89 | 90 | V ?= $(VERBOSE) 91 | ifeq ("$(V)","1") 92 | Q := 93 | vecho := @true 94 | else 95 | Q := @ 96 | vecho := @echo 97 | endif 98 | 99 | vpath %.c $(SRC_DIR) 100 | 101 | define compile-objects 102 | $1/%.o: %.c 103 | $(vecho) "CC $$<" 104 | $(Q) $(CC) $(INCDIR) $(MODULE_INCDIR) $(EXTRA_INCDIR) $(SDK_INCDIR) $(CFLAGS) -c $$< -o $$@ 105 | endef 106 | 107 | .PHONY: all checkdirs flash clean 108 | 109 | all: checkdirs $(TARGET_OUT) $(FW_FILE_1) $(FW_FILE_2) 110 | 111 | $(FW_BASE)/%.bin: $(TARGET_OUT) | $(FW_BASE) 112 | $(vecho) "FW $(FW_BASE)/" 113 | $(Q) $(ESPTOOL) elf2image -o $(FW_BASE)/ $(TARGET_OUT) 114 | 115 | $(TARGET_OUT): $(APP_AR) 116 | $(vecho) "LD $@" 117 | $(Q) $(LD) -L$(SDK_LIBDIR) $(LD_SCRIPT) $(LDFLAGS) -Wl,--start-group $(LIBS) $(APP_AR) -Wl,--end-group -o $@ 118 | 119 | $(APP_AR): $(OBJ) 120 | $(vecho) "AR $@" 121 | $(Q) $(AR) cru $@ $^ 122 | 123 | checkdirs: $(BUILD_DIR) $(FW_BASE) 124 | 125 | $(BUILD_DIR): 126 | $(Q) mkdir -p $@ 127 | 128 | $(FW_BASE): 129 | $(Q) mkdir -p $@ 130 | 131 | flash: $(FW_FILE_1) $(FW_FILE_2) 132 | $(ESPTOOL) --port $(ESPPORT) write_flash $(FW_FILE_1_ADDR) $(FW_FILE_1) $(FW_FILE_2_ADDR) $(FW_FILE_2) 133 | 134 | clean: 135 | $(Q) rm -rf $(FW_BASE) $(BUILD_BASE) 136 | 137 | $(foreach bdir,$(BUILD_DIR),$(eval $(call compile-objects,$(bdir)))) 138 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # esp8266-WifiScanMap 2 | 3 | The aim of this project is to build autonomous device as small as possible. 4 | 5 | Scan and map all 802.11 access point, stations probes and stations in order to fill the [wifiScanMap](https://github.com/mehdilauters/wifiScanMap) database. 6 | ![WifiScanMap](https://github.com/mehdilauters/wifiScanMap/raw/master/doc/main.png) 7 | 8 | It scan over networks, stations, probes request and then synchronize to a central database through a json API through a known wifi spot (essid, password) or through dns tunneling on several open spots ( SFR WIFI FON ). 9 | 10 | The central database compute the device position thanks to already known wifi access point. 11 | 12 | Some tests were done on device shapes: 13 | - magnetic dropable blackbox (36 hour of autonomy) 14 | 15 | ![blackbox open](doc/blackbox_open.png) 16 | ![blackbox closed](doc/blackbox_closed.png) 17 | - usb powered device 18 | 19 | ![blackbox](doc/usb.png) 20 | - solar totally autonomous box powered by battery + solar panels 21 | 22 | 23 | This version was built on the Espressif sdk 1.2 24 | 25 | To set up your config, please check files [user_config.h](user/user_config.h) and [wifis_spots.h](user/wifis_spots.h) 26 | 27 | 28 | Please read the wifiScanMap [Readme](https://github.com/mehdilauters/wifiScanMap/blob/master/README.md) for more information -------------------------------------------------------------------------------- /doc/blackbox_closed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mehdilauters/esp8266-wifiScanMap/8b256b18fded38b3848ac22fa6aea696e52dc5a4/doc/blackbox_closed.png -------------------------------------------------------------------------------- /doc/blackbox_open.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mehdilauters/esp8266-wifiScanMap/8b256b18fded38b3848ac22fa6aea696e52dc5a4/doc/blackbox_open.png -------------------------------------------------------------------------------- /doc/usb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mehdilauters/esp8266-wifiScanMap/8b256b18fded38b3848ac22fa6aea696e52dc5a4/doc/usb.png -------------------------------------------------------------------------------- /user/base64.c: -------------------------------------------------------------------------------- 1 | /* base64.c : base-64 / MIME encode/decode */ 2 | /* PUBLIC DOMAIN - Jon Mayo - November 13, 2003 */ 3 | // #include "c_types.h" 4 | // #include 5 | // #include 6 | // #include 7 | // #include 8 | 9 | #include "os_type.h" 10 | 11 | 12 | #include "base64.h" 13 | 14 | static const uint8_t base64dec_tab[256]= { 15 | 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 16 | 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 17 | 255,255,255,255,255,255,255,255,255,255,255, 62,255,255,255, 63, 18 | 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,255,255,255, 0,255,255, 19 | 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 20 | 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,255,255,255,255,255, 21 | 255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 22 | 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,255,255,255,255,255, 23 | 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 24 | 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 25 | 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 26 | 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 27 | 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 28 | 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 29 | 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 30 | 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 31 | }; 32 | 33 | #if 0 34 | static int ICACHE_FLASH_ATTR base64decode(const char in[4], char out[3]) { 35 | uint8_t v[4]; 36 | v[0]=base64dec_tab[(unsigned)in[0]]; 37 | v[1]=base64dec_tab[(unsigned)in[1]]; 38 | v[2]=base64dec_tab[(unsigned)in[2]]; 39 | v[3]=base64dec_tab[(unsigned)in[3]]; 40 | out[0]=(v[0]<<2)|(v[1]>>4); 41 | out[1]=(v[1]<<4)|(v[2]>>2); 42 | out[2]=(v[2]<<6)|(v[3]); 43 | return (v[0]|v[1]|v[2]|v[3])!=255 ? in[3]=='=' ? in[2]=='=' ? 1 : 2 : 3 : 0; 44 | } 45 | #endif 46 | 47 | /* decode a base64 string in one shot */ 48 | int ICACHE_FLASH_ATTR base64_decode(size_t in_len, const char *in, size_t out_len, unsigned char *out) { 49 | unsigned int ii, io; 50 | uint32_t v; 51 | unsigned int rem; 52 | 53 | for(io=0,ii=0,v=0,rem=0;ii=8) { 62 | rem-=8; 63 | if(io>=out_len) return -1; /* truncation is failure */ 64 | out[io++]=(v>>rem)&255; 65 | } 66 | } 67 | if(rem>=8) { 68 | rem-=8; 69 | if(io>=out_len) return -1; /* truncation is failure */ 70 | out[io++]=(v>>rem)&255; 71 | } 72 | return io; 73 | } 74 | 75 | static const uint8_t base64enc_tab[64]= "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 76 | void base64encode(const unsigned char in[3], unsigned char out[4], int count) { 77 | out[0]=base64enc_tab[(in[0]>>2)]; 78 | out[1]=base64enc_tab[((in[0]&3)<<4)|(in[1]>>4)]; 79 | out[2]=count<2 ? '=' : base64enc_tab[((in[1]&15)<<2)|(in[2]>>6)]; 80 | out[3]=count<3 ? '=' : base64enc_tab[(in[2]&63)]; 81 | } 82 | int base64_encode(size_t in_len, const unsigned char *in, size_t out_len, char *out) { 83 | unsigned ii, io; 84 | // uint_least32_t v; 85 | uint32_t v; 86 | unsigned rem; 87 | for(io=0,ii=0,v=0,rem=0;ii=6) { 93 | rem-=6; 94 | if(io>=out_len) return -1; /* truncation is failure */ 95 | out[io++]=base64enc_tab[(v>>rem)&63]; 96 | } 97 | } 98 | if(rem) { 99 | v<<=(6-rem); 100 | if(io>=out_len) return -1; /* truncation is failure */ 101 | out[io++]=base64enc_tab[v&63]; 102 | } 103 | while(io&3) { 104 | if(io>=out_len) return -1; /* truncation is failure */ 105 | out[io++]='='; 106 | } 107 | if(io>=out_len) return -1; /* no room for null terminator */ 108 | out[io]=0; 109 | return io; 110 | } 111 | -------------------------------------------------------------------------------- /user/base64.h: -------------------------------------------------------------------------------- 1 | #ifndef BASE64_H 2 | #define BASE64_H 3 | // https://github.com/mziwisky/esp8266-dev/blob/master/esphttpd/user/base64.h 4 | 5 | int base64_decode(size_t in_len, const char *in, size_t out_len, unsigned char *out); 6 | int base64_encode(size_t in_len, const unsigned char *in, size_t out_len, char *out); 7 | 8 | #endif -------------------------------------------------------------------------------- /user/data.h: -------------------------------------------------------------------------------- 1 | struct data scanmap; -------------------------------------------------------------------------------- /user/fifo.h: -------------------------------------------------------------------------------- 1 | /** @brief low-level FIFO templace using a circular buffer 2 | * @author JD 3 | */ 4 | 5 | #ifndef FIFO_H 6 | #define FIFO_H 7 | 8 | #ifndef T 9 | #error "T is not defined, define T to your template type" 10 | #endif 11 | 12 | // #include 13 | // #include 14 | #include "os_type.h" 15 | typedef uint8_t bool_t; 16 | 17 | typedef struct { 18 | T *head; 19 | T *tail; 20 | T *data; 21 | uint16_t data_len; 22 | }fifo_t; 23 | 24 | /** @brief Pointer to the end of FIFO */ 25 | #define FIFO_END(fifo) ((fifo)->data + (fifo)->data_len) 26 | 27 | /** @brief Initialize FIFO with buffer 28 | * @param len number of element which can be stored in buffer 29 | * @warning : FIFO can hold size-1 elements */ 30 | static inline void fifo_init(fifo_t *fifo, T *buffer, uint16_t len) { 31 | // initialize buffer 32 | fifo->data = buffer; 33 | fifo->data_len = len; 34 | // set head and tail to start of data buffer 35 | fifo->head = fifo->tail = fifo->data; 36 | } 37 | 38 | /** @brief Clear FIFO, size will be 0 */ 39 | static inline void fifo_clear(fifo_t *fifo) { 40 | // set head and tail to start of data buffer 41 | fifo->head = fifo->tail = fifo->data; 42 | } 43 | 44 | /** @brief Return avaible free space in FIFO */ 45 | static inline uint16_t fifo_freespace(fifo_t *fifo) { 46 | int32_t delta = fifo->data_len - 1 - (fifo->tail - fifo->head); 47 | if(delta >= fifo->data_len) 48 | delta -= fifo->data_len; 49 | return delta; 50 | } 51 | 52 | /** @brief Return stored elements in FIFO */ 53 | static inline uint16_t fifo_size(fifo_t *fifo) { 54 | uint16_t fs = fifo_freespace(fifo); 55 | return fifo->data_len - 1 - fs; 56 | } 57 | 58 | /** @brief Return TRUE if FIFO is full */ 59 | static inline bool_t fifo_isfull(fifo_t *fifo) { 60 | // check if tail+1 equals : 61 | // - end of buffer if head is located at the start of buffer 62 | // - head of buffer otherwise 63 | if(fifo->head == fifo->data) 64 | return fifo->tail+1 == FIFO_END(fifo); 65 | else 66 | return fifo->tail+1 == fifo->head; 67 | } 68 | 69 | /** @brief Return TRUE if FIFO is empty */ 70 | static inline bool_t fifo_isempty(fifo_t *fifo) { 71 | return fifo->tail == fifo->head; 72 | } 73 | 74 | /**@brief Push c to FIFO */ 75 | static inline void fifo_push(fifo_t *fifo, T c) { 76 | *fifo->tail = c; 77 | if(++(fifo->tail) == FIFO_END(fifo)) { 78 | fifo->tail = fifo->data; 79 | } 80 | } 81 | 82 | static inline T fifo_at(fifo_t *fifo, uint16_t index) { 83 | T *c = fifo->head; 84 | uint16_t i; 85 | for(i = 0; i < index; i++) 86 | { 87 | c++; 88 | if(c == FIFO_END(fifo)) { 89 | c = fifo->data; 90 | } 91 | } 92 | return *c; 93 | 94 | 95 | } 96 | 97 | /**@brief Pop from FIFO */ 98 | static inline T fifo_pop(fifo_t *fifo) { 99 | T c = *fifo->head; 100 | if(++(fifo->head) == FIFO_END(fifo)) { 101 | fifo->head = fifo->data; 102 | } 103 | return c; 104 | } 105 | 106 | /**@brief Get FIFO tail */ 107 | static inline T fifo_tail(fifo_t *fifo) { 108 | return *fifo->tail; 109 | } 110 | 111 | /**@brief Get FIFO head, do not pop it */ 112 | static inline T fifo_head(fifo_t *fifo) { 113 | return *fifo->head; 114 | } 115 | 116 | #endif//FIFO_H 117 | -------------------------------------------------------------------------------- /user/scanmap.c: -------------------------------------------------------------------------------- 1 | #include "scanmap.h" 2 | #include "user_config.h" 3 | #include 4 | #include "osapi.h" 5 | 6 | #include "ip_addr.h" 7 | #include "user_interface.h" 8 | #include "sync.h" 9 | #include "wifis_spots.h" 10 | #include "data.h" 11 | 12 | #ifdef LED_TOGGLE_REGISTER 13 | #define LED_TOGGLE() toggle_led(); 14 | #else 15 | #define LED_TOGGLE() 16 | #endif 17 | 18 | static volatile os_timer_t channelHop_timer; 19 | 20 | void channelHop(void *arg) 21 | { 22 | // 1 - 13 channel hopping 23 | uint8 new_channel = wifi_get_channel() % 12 + 1; 24 | wifi_set_channel(new_channel); 25 | } 26 | 27 | uint8_t broadcast1[3] = { 0x01, 0x00, 0x5e }; 28 | uint8_t broadcast2[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; 29 | uint8_t broadcast3[3] = { 0x33, 0x33, 0x00 }; 30 | 31 | 32 | void ICACHE_FLASH_ATTR scanmap_clear() { 33 | fifo_clear(&scanmap.beaconsinfos); 34 | fifo_clear(&scanmap.probesinfos); 35 | fifo_clear(&scanmap.clientsinfos); 36 | } 37 | 38 | void ICACHE_FLASH_ATTR print_beacon(struct beaconinfo beacon) 39 | { 40 | if (beacon.err != 0) { 41 | //os_printf("BEACON ERR: (%d) ", beacon.err); 42 | } else { 43 | os_printf("BEACON: [%32s] ", beacon.ssid); 44 | int i = 0; 45 | for (i = 0; i < 6; i++) os_printf("%02x", beacon.bssid[i]); 46 | os_printf(" %2d", beacon.channel); 47 | if(! beacon.encryption ) { 48 | os_printf(" OPN"); 49 | } else { 50 | os_printf(" KEY"); 51 | } 52 | os_printf(" %4d\r\n", beacon.rssi); 53 | } 54 | } 55 | 56 | void ICACHE_FLASH_ATTR print_probe(struct probeinfo pi) 57 | { 58 | if (pi.err != 0) { 59 | //os_printf("PROBE ERR: (%d) ", beacon.err); 60 | } else { 61 | os_printf("PROBE: [%32s] ", pi.ssid); 62 | int i = 0; 63 | for (i = 0; i < 6; i++) os_printf("%02x", pi.bssid[i]); 64 | os_printf("\r\n"); 65 | } 66 | } 67 | 68 | void ICACHE_FLASH_ATTR print_client(struct clientinfo ci) 69 | { 70 | uint16_t u = 0; 71 | int i = 0; 72 | int known = 0; // Clear known flag 73 | if (ci.err != 0) { 74 | } else { 75 | os_printf("CLIENT: "); 76 | int i = 0; 77 | for (i = 0; i < 6; i++) os_printf("%02x", ci.station[i]); 78 | os_printf(" works with: "); 79 | struct beaconinfo item = fifo_at(&scanmap.beaconsinfos, u).beaconinfo; 80 | for (u = 0; u < fifo_size(&scanmap.clientsinfos); u++) 81 | { 82 | if (! memcmp(item.bssid, ci.bssid, ETH_MAC_LEN)) { 83 | os_printf("[%32s]", item.ssid); 84 | known = 1; 85 | break; 86 | } // AP known => Set known flag 87 | } 88 | if (! known) { 89 | os_printf("%22s", " "); 90 | for (i = 0; i < 6; i++) os_printf("%02x", ci.bssid[i]); 91 | } 92 | 93 | os_printf("%5s", " "); 94 | for (i = 0; i < 6; i++) os_printf("%02x", ci.ap[i]); 95 | os_printf("%5s", " "); 96 | 97 | if (! known) { 98 | os_printf(" %3d", ci.channel); 99 | } else { 100 | os_printf(" %3d", item.channel); 101 | } 102 | os_printf(" %4d\r\n", ci.rssi); 103 | } 104 | } 105 | 106 | bool is_valid_string(char * _s, int _len) { 107 | int i; 108 | for(i = 0; i<_len; i++) { 109 | if(_s[i] < 32 || _s[i] > 126) { 110 | return false; 111 | } 112 | } 113 | return true; 114 | } 115 | 116 | struct probeinfo ICACHE_FLASH_ATTR parse_probe(uint8_t *frame, uint16_t framelen) 117 | { 118 | struct probeinfo pi; 119 | pi.ssid_len = 0; 120 | pi.err = 0; 121 | int pos = 24; 122 | if (frame[pos] == 0x00) { 123 | while (pos < framelen) { 124 | switch (frame[pos]) { 125 | case 0x00: //SSID 126 | pi.ssid_len = (int) frame[pos + 1]; 127 | if (pi.ssid_len == 0) { 128 | memset(pi.ssid, '\x00', 33); 129 | break; 130 | } 131 | if (pi.ssid_len < 2) { 132 | pi.err = -1; 133 | break; 134 | } 135 | if (pi.ssid_len > 32) { 136 | pi.err = -2; 137 | break; 138 | } 139 | memset(pi.ssid, '\x00', 33); 140 | memcpy(pi.ssid, frame + pos + 2, pi.ssid_len); 141 | 142 | pi.err = !is_valid_string(pi.ssid, pi.ssid_len); 143 | 144 | break; 145 | } 146 | pos++; 147 | } 148 | } 149 | memcpy(pi.bssid, frame + 10, ETH_MAC_LEN); 150 | pi.time_s = get_seconds(); 151 | return pi; 152 | } 153 | 154 | struct beaconinfo ICACHE_FLASH_ATTR parse_beacon(uint8_t *frame, uint16_t framelen, signed rssi) 155 | { 156 | struct beaconinfo bi; 157 | bi.ssid_len = 0; 158 | bi.channel = 0; 159 | bi.err = 0; 160 | bi.rssi = rssi; 161 | bi.encryption = false; 162 | int pos = 36; 163 | bool ssid_found = false; 164 | if (frame[pos] == 0x00) { 165 | while (pos < framelen) { 166 | switch (frame[pos]) { 167 | case 0x00: //SSID 168 | if(ssid_found) break; 169 | ssid_found = true; 170 | bi.ssid_len = (int) frame[pos + 1]; 171 | if (bi.ssid_len == 0) { 172 | memset(bi.ssid, '\x00', 33); 173 | break; 174 | } 175 | if (bi.ssid_len < 0) { 176 | bi.err = -1; 177 | break; 178 | } 179 | if (bi.ssid_len > 32) { 180 | bi.err = -2; 181 | break; 182 | } 183 | 184 | 185 | memset(bi.ssid, '\x00', 33); 186 | memcpy(bi.ssid, frame + pos + 2, bi.ssid_len); 187 | 188 | bi.err = !is_valid_string(bi.ssid, bi.ssid_len); 189 | 190 | if(!bi.err && !scanmap.wififound) { 191 | int i; 192 | for(i=0; i < sizeof(wifis_spots) / sizeof(struct wifi); i++) { 193 | if (! memcmp(wifis_spots[i].essid, bi.ssid, bi.ssid_len)) { 194 | if(bi.rssi > SYNC_MIN_LEVEL) { 195 | scanmap.wififound = true; 196 | blink_led(5, 500); 197 | } 198 | } 199 | } 200 | } 201 | 202 | break; 203 | case 0x03: //Channel 204 | bi.channel = (int) frame[pos + 2]; 205 | //pos = -1; 206 | break; 207 | case 48: //RSN 208 | bi.encryption = true; 209 | //pos = -1; 210 | break; 211 | default: 212 | break; 213 | } 214 | if (pos < 0) break; 215 | pos += (int) frame[pos + 1] + 2; 216 | } 217 | } else { 218 | bi.err = -3; 219 | } 220 | 221 | bi.capa[0] = frame[34]; 222 | bi.capa[1] = frame[35]; 223 | memcpy(bi.bssid, frame + 10, ETH_MAC_LEN); 224 | 225 | bi.time_s = get_seconds(); 226 | 227 | return bi; 228 | } 229 | 230 | struct clientinfo ICACHE_FLASH_ATTR parse_data(uint8_t *frame, uint16_t framelen, signed rssi, unsigned channel) 231 | { 232 | struct clientinfo ci; 233 | ci.channel = channel; 234 | ci.err = 0; 235 | ci.rssi = rssi; 236 | int pos = 36; 237 | uint8_t *bssid; 238 | uint8_t *station; 239 | uint8_t *ap; 240 | uint8_t ds; 241 | 242 | ds = frame[1] & 3; //Set first 6 bits to 0 243 | switch (ds) { 244 | // p[1] - xxxx xx00 => NoDS p[4]-DST p[10]-SRC p[16]-BSS 245 | case 0: 246 | bssid = frame + 16; 247 | station = frame + 10; 248 | ap = frame + 4; 249 | break; 250 | // p[1] - xxxx xx01 => ToDS p[4]-BSS p[10]-SRC p[16]-DST 251 | case 1: 252 | bssid = frame + 4; 253 | station = frame + 10; 254 | ap = frame + 16; 255 | break; 256 | // p[1] - xxxx xx10 => FromDS p[4]-DST p[10]-BSS p[16]-SRC 257 | case 2: 258 | bssid = frame + 10; 259 | // hack - don't know why it works like this... 260 | if (memcmp(frame + 4, broadcast1, 3) || memcmp(frame + 4, broadcast2, 3) || memcmp(frame + 4, broadcast3, 3)) { 261 | station = frame + 16; 262 | ap = frame + 4; 263 | } else { 264 | station = frame + 4; 265 | ap = frame + 16; 266 | } 267 | break; 268 | // p[1] - xxxx xx11 => WDS p[4]-RCV p[10]-TRM p[16]-DST p[26]-SRC 269 | case 3: 270 | bssid = frame + 10; 271 | station = frame + 4; 272 | ap = frame + 4; 273 | break; 274 | } 275 | 276 | memcpy(ci.station, station, ETH_MAC_LEN); 277 | memcpy(ci.bssid, bssid, ETH_MAC_LEN); 278 | memcpy(ci.ap, ap, ETH_MAC_LEN); 279 | 280 | ci.seq_n = frame[23] * 0xFF + (frame[22] & 0xF0); 281 | 282 | ci.time_s = get_seconds(); 283 | return ci; 284 | } 285 | 286 | 287 | int ICACHE_FLASH_ATTR register_beacon(struct beaconinfo beacon) 288 | { 289 | int known = 0; // Clear known flag 290 | uint16_t u = 0; 291 | for (u = 0; u < fifo_size(&scanmap.beaconsinfos); u++) 292 | { 293 | struct beaconinfo item = fifo_at(&scanmap.beaconsinfos, u).beaconinfo; 294 | if (! memcmp(item.bssid, beacon.bssid, ETH_MAC_LEN)) { 295 | known = 1; 296 | break; 297 | } // AP known => Set known flag 298 | } 299 | if (! known) // AP is NEW, copy MAC to array and return it 300 | { 301 | 302 | bool synced = false; 303 | if(fifo_isfull(&scanmap.beaconsinfos)) { 304 | fifo_pop(&scanmap.beaconsinfos); 305 | os_printf("exceeded max scanmap.aps_known\n"); 306 | if(SYNC_TYPE == sync_type_full || SYNC_TYPE == sync_type_both) { 307 | sync_sync(); 308 | synced = true; 309 | } 310 | } 311 | if(!synced && SYNC_TYPE == sync_type_position) { 312 | if(fifo_size(&scanmap.beaconsinfos) >= MIN_SYNCING_BEST_AP) { 313 | sync_sync(); 314 | } 315 | } 316 | if(!fifo_isfull(&scanmap.beaconsinfos)) { 317 | union data_item item; 318 | item.beaconinfo = beacon; 319 | fifo_push(&scanmap.beaconsinfos, item); 320 | LED_TOGGLE(); 321 | } 322 | } 323 | return known; 324 | } 325 | 326 | int ICACHE_FLASH_ATTR register_probe(struct probeinfo pi) 327 | { 328 | if(pi.err) { 329 | return 0; 330 | } 331 | int known = 0; // Clear known flag 332 | uint16_t u = 0; 333 | for (u = 0; u < fifo_size(&scanmap.probesinfos); u++) 334 | { 335 | struct probeinfo item = fifo_at(&scanmap.probesinfos,u).probeinfo; 336 | bool mac_equals = memcmp(item.bssid, pi.bssid, ETH_MAC_LEN) == 0; 337 | bool ssid_equals = ( item.ssid_len == pi.ssid_len && memcmp(item.ssid, pi.ssid, item.ssid_len) ==0); 338 | // os_printf("%d - %d\n",mac_equals, ssid_equals); 339 | if ( mac_equals && ssid_equals) { 340 | known = 1; 341 | break; 342 | } 343 | } 344 | if (! known) 345 | { 346 | if(fifo_isfull(&scanmap.probesinfos) && MAX_PROBES_TRACKED != 0) { 347 | fifo_pop(&scanmap.probesinfos); 348 | os_printf("exceeded max scanmap.probes_known\n"); 349 | if(SYNC_TYPE == sync_type_full || SYNC_TYPE == sync_type_both) { 350 | sync_sync(); 351 | } 352 | } 353 | if(!fifo_isfull(&scanmap.probesinfos)) { 354 | union data_item item; 355 | item.probeinfo = pi; 356 | fifo_push(&scanmap.probesinfos, item); 357 | LED_TOGGLE(); 358 | } 359 | } 360 | return known; 361 | } 362 | 363 | int ICACHE_FLASH_ATTR register_client(struct clientinfo ci) 364 | { 365 | int known = 0; // Clear known flag 366 | uint16_t u = 0; 367 | for (u = 0; u < fifo_size(&scanmap.clientsinfos); u++) 368 | { 369 | struct clientinfo item = fifo_at(&scanmap.clientsinfos,u).clientinfo; 370 | if (! memcmp(item.station, ci.station, ETH_MAC_LEN) && get_seconds() - ci.time_s < CLIENT_MAX_TIME) { 371 | known = 1; 372 | break; 373 | } 374 | } 375 | if (! known) 376 | { 377 | if(fifo_isfull(&scanmap.clientsinfos) && MAX_CLIENTS_TRACKED != 0) { 378 | fifo_pop(&scanmap.clientsinfos); 379 | os_printf("exceeded max scanmap.clients_known\n"); 380 | if(SYNC_TYPE == sync_type_full || SYNC_TYPE == sync_type_both) { 381 | sync_sync(); 382 | } 383 | } 384 | if(! fifo_isfull(&scanmap.clientsinfos)) { 385 | union data_item item; 386 | item.clientinfo = ci; 387 | fifo_push(&scanmap.clientsinfos, item); 388 | LED_TOGGLE(); 389 | } 390 | } 391 | return known; 392 | } 393 | 394 | /* ============================================== 395 | * Promiscous callback structures, see ESP manual 396 | * ============================================== */ 397 | 398 | struct RxControl { 399 | signed rssi:8; 400 | // signal intensity of packet 401 | unsigned rate:4; 402 | unsigned is_group:1; 403 | unsigned:1; 404 | unsigned sig_mode:2; 405 | // 0:is 11n packet; 1:is not 11n packet; 406 | unsigned legacy_length:12; // if not 11n packet, shows length of packet. 407 | unsigned damatch0:1; 408 | unsigned damatch1:1; 409 | unsigned bssidmatch0:1; 410 | unsigned bssidmatch1:1; 411 | unsigned MCS:7; 412 | // if is 11n packet, shows the modulation 413 | // and code used (range from 0 to 76) 414 | unsigned CWB:1; // if is 11n packet, shows if is HT40 packet or not 415 | unsigned HT_length:16;// if is 11n packet, shows length of packet. 416 | unsigned Smoothing:1; 417 | unsigned Not_Sounding:1; 418 | unsigned:1; 419 | unsigned Aggregation:1; 420 | unsigned STBC:2; 421 | unsigned FEC_CODING:1; // if is 11n packet, shows if is LDPC packet or not. 422 | unsigned SGI:1; 423 | unsigned rxend_state:8; 424 | unsigned ampdu_cnt:8; 425 | unsigned channel:4; //which channel this packet in. 426 | unsigned:12; 427 | }; 428 | struct LenSeq{ 429 | u16 len; // length of packet 430 | u16 seq; // serial number of packet, the high 12bits are serial number, 431 | // low 14 bits are Fragment number (usually be 0) 432 | u8 addr3[6]; // the third address in packet 433 | }; 434 | struct sniffer_buf{ 435 | struct RxControl rx_ctrl; 436 | u8 buf[36 ]; // head of ieee80211 packet 437 | u16 cnt; 438 | // number count of packet 439 | struct LenSeq lenseq[1]; 440 | //length of packet 441 | }; 442 | struct sniffer_buf2{ 443 | struct RxControl rx_ctrl; 444 | u8 buf[112]; 445 | u16 cnt; 446 | u16 len; 447 | //length of packet 448 | }; 449 | 450 | 451 | 452 | void ICACHE_FLASH_ATTR promisc_cb(uint8_t *buf, uint16_t len) 453 | { 454 | int i = 0; 455 | uint16_t seq_n_new = 0; 456 | if (len == 12) { 457 | struct RxControl *sniffer = (struct RxControl*) buf; 458 | } else if (len == 128) { 459 | struct sniffer_buf2 *sniffer = (struct sniffer_buf2*) buf; 460 | 461 | if(sniffer->buf[0] == 0x80) { 462 | struct beaconinfo beacon = parse_beacon(sniffer->buf, 112, sniffer->rx_ctrl.rssi); 463 | 464 | if (register_beacon(beacon) == 0) { 465 | #ifdef PRINT_ELEMENTS 466 | print_beacon(beacon); 467 | #endif 468 | scanmap.nothing_new = 0; 469 | } 470 | } else if(sniffer->buf[0] == 0x40) { 471 | struct probeinfo pi = parse_probe(sniffer->buf, 34); 472 | if(strlen(pi.ssid) != 0) { 473 | if(register_probe(pi) == 0) { 474 | #ifdef PRINT_ELEMENTS 475 | print_probe(pi); 476 | #endif 477 | scanmap.nothing_new = 0; 478 | } 479 | } 480 | } 481 | } else { 482 | //Serial.println(len); 483 | struct sniffer_buf *sniffer = (struct sniffer_buf*) buf; 484 | //Is data or QOS? 485 | if ((sniffer->buf[0] == 0x08) || (sniffer->buf[0] == 0x88)) { 486 | struct clientinfo ci = parse_data(sniffer->buf, 36, sniffer->rx_ctrl.rssi, sniffer->rx_ctrl.channel); 487 | if (memcmp(ci.bssid, ci.station, ETH_MAC_LEN)) { 488 | if (register_client(ci) == 0) { 489 | #ifdef PRINT_ELEMENTS 490 | print_client(ci); 491 | #endif 492 | scanmap.nothing_new = 0; 493 | } 494 | } 495 | } 496 | } 497 | } 498 | 499 | 500 | 501 | 502 | void ICACHE_FLASH_ATTR enable_monitor() { 503 | os_printf("enable monitor\n"); 504 | os_timer_arm(&channelHop_timer, CHANNEL_HOP_INTERVAL, 1); 505 | 506 | // Promiscuous works only with station mode 507 | wifi_station_disconnect(); 508 | wifi_set_opmode(STATION_MODE); 509 | wifi_promiscuous_enable(0); 510 | wifi_set_promiscuous_rx_cb(promisc_cb); 511 | wifi_promiscuous_enable(1); 512 | } 513 | 514 | void ICACHE_FLASH_ATTR disable_monitor() { 515 | os_printf("disable monitor\n"); 516 | os_timer_disarm(&channelHop_timer); 517 | wifi_promiscuous_enable(0); 518 | wifi_set_promiscuous_rx_cb(0); 519 | } 520 | 521 | void ICACHE_FLASH_ATTR scanmap_enable() { 522 | enable_monitor(); 523 | } 524 | 525 | 526 | void ICACHE_FLASH_ATTR scanmap_reset() { 527 | scanmap_clear(); 528 | enable_monitor(); 529 | } 530 | 531 | bool ICACHE_FLASH_ATTR scanmap_print_fifos_sizes() { 532 | os_printf("beacons %d\n",fifo_size(&scanmap.beaconsinfos)); 533 | os_printf("probes %d\n",fifo_size(&scanmap.probesinfos)); 534 | os_printf("clients %d\n",fifo_size(&scanmap.clientsinfos)); 535 | } 536 | 537 | bool ICACHE_FLASH_ATTR scanmap_isempty() { 538 | return fifo_isempty(&scanmap.beaconsinfos) && fifo_isempty(&scanmap.probesinfos) && fifo_isempty(&scanmap.clientsinfos); 539 | } 540 | 541 | bool ICACHE_FLASH_ATTR scanmap_isfull() { 542 | return fifo_isfull(&scanmap.beaconsinfos) || fifo_isfull(&scanmap.probesinfos) || fifo_isfull(&scanmap.clientsinfos); 543 | } 544 | 545 | struct wifi * ICACHE_FLASH_ATTR scanmap_get_available_wifi() { 546 | uint8_t i,u; 547 | 548 | for(i=0; i < sizeof(wifis_spots) / sizeof(struct wifi); i++) { 549 | 550 | for (u = 0; u < fifo_size(&scanmap.beaconsinfos); u++) 551 | { 552 | struct beaconinfo item = fifo_at(&scanmap.beaconsinfos, u).beaconinfo; 553 | // check for any open network 554 | if(strlen(wifis_spots[i].essid) == 0 && ! item.encryption && item.rssi >= SYNC_MIN_LEVEL) { 555 | return &wifis_spots[i]; 556 | } else if(strlen(wifis_spots[i].essid) == item.ssid_len) 557 | if (! memcmp(wifis_spots[i].essid, item.ssid, item.ssid_len) && item.rssi >= SYNC_MIN_LEVEL) { 558 | return &wifis_spots[i]; 559 | } 560 | } 561 | } 562 | return NULL; 563 | } 564 | 565 | void ICACHE_FLASH_ATTR scanmap_init() { 566 | 567 | fifo_init(&scanmap.beaconsinfos, scanmap.beacons_buffer, MAX_APS_TRACKED+1); 568 | fifo_init(&scanmap.probesinfos, scanmap.probes_buffer, MAX_PROBES_TRACKED+1); 569 | fifo_init(&scanmap.clientsinfos, scanmap.clients_buffer, MAX_CLIENTS_TRACKED+1); 570 | 571 | scanmap.wififound = false; 572 | 573 | os_timer_disarm(&channelHop_timer); 574 | os_timer_setfn(&channelHop_timer, (os_timer_func_t *) channelHop, NULL); 575 | 576 | scanmap_reset(); 577 | } -------------------------------------------------------------------------------- /user/scanmap.h: -------------------------------------------------------------------------------- 1 | #ifndef SCANMAP_H 2 | #define SCANMAP_H 3 | 4 | #include "user_config.h" 5 | #include "os_type.h" 6 | 7 | struct wifi { 8 | char essid[33]; 9 | char password[33]; 10 | }; 11 | 12 | 13 | 14 | struct beaconinfo 15 | { 16 | uint32_t time_s; 17 | uint8_t bssid[ETH_MAC_LEN]; 18 | uint8_t ssid[33]; 19 | int ssid_len; 20 | int channel; 21 | int err; 22 | signed rssi; 23 | bool encryption; 24 | uint8_t capa[2]; 25 | }; 26 | 27 | struct probeinfo 28 | { 29 | uint32_t time_s; 30 | uint8_t bssid[ETH_MAC_LEN]; 31 | int ssid_len; 32 | uint8_t ssid[33]; 33 | int err; 34 | }; 35 | 36 | struct clientinfo 37 | { 38 | uint32_t time_s; 39 | uint8_t bssid[ETH_MAC_LEN]; 40 | uint8_t station[ETH_MAC_LEN]; 41 | uint8_t ap[ETH_MAC_LEN]; 42 | int channel; 43 | int err; 44 | signed rssi; 45 | uint16_t seq_n; 46 | }; 47 | 48 | 49 | union data_item { 50 | struct beaconinfo beaconinfo; 51 | struct clientinfo clientinfo; 52 | struct probeinfo probeinfo; 53 | }; 54 | 55 | #define T union data_item 56 | #include "fifo.h" 57 | 58 | struct data { 59 | fifo_t beaconsinfos; 60 | fifo_t probesinfos; 61 | fifo_t clientsinfos; 62 | 63 | union data_item beacons_buffer[MAX_APS_TRACKED + 1]; 64 | union data_item probes_buffer[MAX_PROBES_TRACKED + 1]; 65 | union data_item clients_buffer[MAX_CLIENTS_TRACKED + 1]; 66 | 67 | int nothing_new; 68 | bool wififound; 69 | }; 70 | 71 | #undef T 72 | 73 | void ICACHE_FLASH_ATTR scanmap_init(); 74 | 75 | // enable scanning 76 | void ICACHE_FLASH_ATTR scanmap_enable(); 77 | 78 | // clear all fifos 79 | void ICACHE_FLASH_ATTR scanmap_reset(); 80 | 81 | // check if at least on fifo is empty 82 | bool ICACHE_FLASH_ATTR scanmap_isempty(); 83 | 84 | // check if at least one fifo is full 85 | bool ICACHE_FLASH_ATTR scanmap_isfull(); 86 | 87 | // print all fifo size 88 | bool ICACHE_FLASH_ATTR scanmap_print_fifos_sizes(); 89 | 90 | // return a known wifi to connect 91 | struct wifi * ICACHE_FLASH_ATTR scanmap_get_available_wifi(); 92 | 93 | #endif -------------------------------------------------------------------------------- /user/sync.c: -------------------------------------------------------------------------------- 1 | 2 | #include "sync.h" 3 | #include "scanmap.h" 4 | #include "user_config.h" 5 | #include "user_json.h" 6 | #include 7 | #include "osapi.h" 8 | #include "upgrade.h" 9 | #include "ip_addr.h" 10 | #include "user_interface.h" 11 | #include "ip_addr.h" 12 | #include "espconn.h" 13 | #include "data.h" 14 | 15 | #define WATCHDOG_MS 10000 16 | 17 | #ifdef SYNC_SSL 18 | # define CONNECT(conn) espconn_secure_connect( conn ) 19 | # define DISCONNECT(conn) espconn_secure_disconnect( conn ) 20 | # define SEND(conn, buffer, len) espconn_secure_sent(conn, buffer, len) 21 | 22 | unsigned char *default_certificate; 23 | unsigned int default_certificate_len = 0; 24 | unsigned char *default_private_key; 25 | unsigned int default_private_key_len = 0; 26 | 27 | #else 28 | # define CONNECT(conn) espconn_connect( conn ) 29 | # define DISCONNECT(conn) espconn_disconnect( conn ) 30 | # define SEND(conn, buffer, len) espconn_sent(conn, buffer, len) 31 | #endif 32 | 33 | struct espconn sync_conn; 34 | ip_addr_t sync_ip; 35 | ip_addr_t my_ip; 36 | esp_tcp sync_tcp; 37 | 38 | 39 | # define MAX_BUFFER_SIZE 2048 40 | 41 | char buffer[ MAX_BUFFER_SIZE ]; 42 | 43 | #ifdef SYNC_DNS 44 | 45 | #define B64_LENGTH(n) (((4 * n / 3) + 3) & ~3) 46 | 47 | // b64 size 48 | # define MAX_B64_SIZE 20 49 | #define B64_BUFFER_SIZE B64_LENGTH(MAX_B64_SIZE) + 20 50 | 51 | static void send_dns_data(bool retry); 52 | static void dns_sync_done( const char *name, ip_addr_t *ipaddr, void *arg ); 53 | char b64_buffer[ B64_BUFFER_SIZE ]; 54 | int total_size = 0; 55 | int already_sent = 0; 56 | int dns_tries = 0; 57 | int dns_last_send = 0; 58 | int dns_frame_id =0; 59 | 60 | #endif 61 | 62 | static volatile os_timer_t sync_timer; 63 | static volatile os_timer_t watchdog_timer; 64 | 65 | static void tcp_connect( void *arg ); 66 | 67 | 68 | bool json_put_char(char c) { 69 | if(strlen(buffer) + 2 >= MAX_BUFFER_SIZE) { 70 | return false; 71 | } 72 | os_sprintf(buffer,"%s%c",buffer, c); 73 | return true; 74 | } 75 | 76 | bool json_put_string(char *s) { 77 | if(strlen(buffer) + strlen(s) +1 >= MAX_BUFFER_SIZE) { 78 | os_printf("Size limit: %d",strlen(buffer)); 79 | return false; 80 | } 81 | os_sprintf(buffer,"%s%s",buffer, s); 82 | return true; 83 | } 84 | 85 | void connect_station(struct wifi _wifi) { 86 | 87 | os_timer_arm(&watchdog_timer, WATCHDOG_MS, 1); 88 | os_printf("Connecting to %s\n",_wifi.essid); 89 | 90 | wifi_set_opmode(STATION_MODE); 91 | static struct station_config config; 92 | config.bssid_set = 0; 93 | os_memcpy( &config.ssid, _wifi.essid, strlen(_wifi.essid) ); 94 | if(strlen(_wifi.password) > 0) { 95 | os_memcpy( &config.password, _wifi.password, strlen(_wifi.password) ); 96 | } else { 97 | *config.password = 0; 98 | } 99 | wifi_station_set_config_current( &config ); 100 | wifi_station_connect(); 101 | } 102 | 103 | void sync_sync() 104 | { 105 | struct wifi * w = scanmap_get_available_wifi(); 106 | if(w != NULL) { 107 | os_timer_disarm(&sync_timer); 108 | disable_monitor(); 109 | os_printf(">>\n"); 110 | connect_station(*w); 111 | } else { 112 | os_printf("--\n"); 113 | } 114 | } 115 | 116 | void sync_cb(void *arg) 117 | { 118 | if(SYNC_TYPE == sync_type_time || SYNC_TYPE == sync_type_both) { 119 | sync_sync(); 120 | } 121 | } 122 | 123 | void sync_done(bool ok) { 124 | os_timer_disarm(&sync_timer); 125 | os_printf("<<\n"); 126 | 127 | #ifdef USE_OTA 128 | if(!handleUpgrade(2, "192.168.211.145",8000,"build/app.out")) { 129 | #endif 130 | wifi_station_disconnect(); 131 | scanmap_enable(); 132 | os_timer_arm(&sync_timer, SYNC_PERIOD, 1); 133 | 134 | #ifdef USE_OTA 135 | } 136 | #endif 137 | 138 | } 139 | 140 | void watchdog_cb(void *arg) { 141 | os_timer_disarm(&watchdog_timer); 142 | sync_done(false); 143 | } 144 | 145 | 146 | #ifdef SYNC_HTTP 147 | void send_data( void *arg ) { 148 | struct espconn *conn = arg; 149 | os_memset(buffer, 0, MAX_BUFFER_SIZE); 150 | os_sprintf( buffer, "POST %s HTTP/1.1\r\nHost: %s\r\nConnection: close\r\nContent-Type: application/json\r\nContent-Length: ", SYNC_PATH, SYNC_HOST); 151 | os_sprintf( buffer, "%s\r\n\r\n",buffer); 152 | int size = strlen(buffer); 153 | build_json(&scanmap); 154 | 155 | int new_size = strlen(buffer); 156 | char tmp[6]; 157 | os_sprintf( tmp, "%5d", new_size - size); 158 | os_memcpy(&buffer[size-5 - 4], tmp, 5); 159 | SEND( conn, buffer, os_strlen( buffer ) ); 160 | } 161 | #endif 162 | 163 | 164 | #ifdef SYNC_DNS 165 | void send_dns_data( bool retry ) { 166 | 167 | if(! retry ) 168 | { 169 | 170 | if(already_sent == total_size || already_sent == 0) 171 | { 172 | os_memset(b64_buffer, 0, MAX_B64_SIZE); 173 | os_memset(buffer, 0, MAX_BUFFER_SIZE); 174 | build_json(&scanmap); 175 | total_size = strlen(buffer); 176 | already_sent = 0; 177 | dns_frame_id = 0; 178 | } 179 | 180 | // 181 | // +1 because of the subdomain '.' and +1 because of \0 182 | int host_size = strlen(SYNC_HOST) +1+1; 183 | 184 | int size = MAX_B64_SIZE - 4; 185 | if(total_size - already_sent < size) { 186 | size = total_size - already_sent; 187 | } 188 | char tmp[MAX_B64_SIZE]; 189 | os_memset(tmp,0,MAX_B64_SIZE); 190 | 191 | uint32_t id = system_get_chip_id(); 192 | os_sprintf(tmp,"%8d",id); 193 | os_sprintf(tmp+8,"%2d",dns_frame_id); 194 | 195 | // add random to avoid cache 196 | uint16_t rand = os_random(); 197 | os_sprintf(tmp+8 + 2,"%4d",rand); 198 | os_memcpy( tmp+8 + 2 + 4, buffer+already_sent, size); 199 | 200 | int count = base64_encode(size+2+8 + 4, tmp, B64_BUFFER_SIZE, b64_buffer); 201 | dns_last_send = size; 202 | already_sent += size; 203 | char host[255]; 204 | os_sprintf(host,".%s",SYNC_HOST); 205 | os_strcpy(b64_buffer+count,host); 206 | } 207 | err_t res = espconn_gethostbyname( &sync_conn, b64_buffer, &sync_ip, dns_sync_done ); 208 | if(res != ESPCONN_OK && res != ESPCONN_INPROGRESS) { 209 | os_printf("DNS error %d\n",res); 210 | } 211 | } 212 | #endif 213 | 214 | #ifdef SYNC_HTTP 215 | void data_received( void *arg, char *pdata, unsigned short len ) 216 | { 217 | os_printf( "%s: %s\n", __FUNCTION__, pdata ); 218 | } 219 | 220 | void check_data(void *arg) { 221 | if(scanmap_isempty()) { 222 | struct espconn *conn = arg; 223 | espconn_delete(conn); 224 | sync_done(true); 225 | } else { 226 | os_printf("sending more data\n"); 227 | tcp_connect( arg ); 228 | } 229 | } 230 | 231 | void data_sent(void *arg) { 232 | struct espconn *conn = arg; 233 | DISCONNECT( conn ); 234 | check_data(arg); 235 | } 236 | 237 | void tcp_connected( void *arg ) 238 | { 239 | struct espconn *conn = arg; 240 | espconn_regist_recvcb( conn, data_received ); 241 | espconn_regist_sentcb( conn, data_sent); 242 | 243 | send_data(arg); 244 | } 245 | 246 | 247 | void tcp_disconnected( void *arg ) 248 | { 249 | check_data(arg); 250 | } 251 | 252 | static void ICACHE_FLASH_ATTR tcp_reconnect(void *arg, 253 | sint8 errType) { 254 | os_printf("tcp connect failed\n"); 255 | struct espconn *pespconn = (struct espconn *) arg; 256 | espconn_delete(pespconn); 257 | sync_done(false); 258 | } 259 | 260 | void tcp_connect( void *arg ) { 261 | uint8_t count; 262 | struct espconn *conn = arg; 263 | 264 | for(count = 0; count < MAX_TRIES; count++) { 265 | if(CONNECT(conn)) { 266 | break; 267 | } 268 | } 269 | } 270 | void dns_done( const char *name, ip_addr_t *ipaddr, void *arg ) 271 | { 272 | if ( ipaddr == NULL) 273 | { 274 | os_printf("DNS lookup failed\n"); 275 | sync_done(false); 276 | } 277 | else 278 | { 279 | os_printf("found server %d.%d.%d.%d\n", 280 | *((uint8 *)&ipaddr->addr), *((uint8 *)&ipaddr->addr + 1), *((uint8 *)&ipaddr->addr + 2), *((uint8 *)&ipaddr->addr + 3)); 281 | 282 | struct espconn *conn = arg; 283 | 284 | conn->type = ESPCONN_TCP; 285 | conn->state = ESPCONN_NONE; 286 | conn->proto.tcp=&sync_tcp; 287 | conn->proto.tcp->local_port = espconn_port(); 288 | conn->proto.tcp->remote_port = SYNC_PORT; 289 | os_memcpy( conn->proto.tcp->remote_ip, &ipaddr->addr, 4 ); 290 | 291 | espconn_regist_connectcb( conn, tcp_connected ); 292 | espconn_regist_disconcb( conn, tcp_disconnected ); 293 | espconn_regist_reconcb(conn, tcp_reconnect); 294 | 295 | 296 | tcp_connect(arg); 297 | } 298 | } 299 | 300 | #endif 301 | 302 | #ifdef SYNC_DNS 303 | 304 | bool dns_ok(ip_addr_t *ipaddr){ 305 | bool ok = *((uint8 *)&ipaddr->addr) == 0 && *((uint8 *)&ipaddr->addr + 1) == 0 && *((uint8 *)&ipaddr->addr + 2) == 0 && *((uint8 *)&ipaddr->addr + 3) == 0; 306 | if(!ok) { 307 | os_printf("protocol error %d.%d.%d.%d\n", 308 | *((uint8 *)&ipaddr->addr), *((uint8 *)&ipaddr->addr + 1), *((uint8 *)&ipaddr->addr + 2), *((uint8 *)&ipaddr->addr + 3)); 309 | } 310 | return ok; 311 | } 312 | 313 | void dns_sync_done( const char *name, ip_addr_t *ipaddr, void *arg ) { 314 | if ( ipaddr == NULL) 315 | { 316 | os_printf("DNS lookup failed "); 317 | dns_tries++; 318 | if(dns_tries >= MAX_TRIES) { 319 | os_printf("aborting\n"); 320 | dns_tries = 0; 321 | total_size = 0; 322 | already_sent = 0; 323 | dns_frame_id = 0; 324 | sync_done(false); 325 | return; 326 | } 327 | already_sent -= dns_last_send; 328 | os_printf("retrying\n"); 329 | send_dns_data(true); 330 | } 331 | else 332 | { 333 | if(dns_ok(ipaddr)) 334 | { 335 | dns_frame_id++; 336 | dns_tries = 0; 337 | // os_printf("DNS SYNC DONE %d %d\n",already_sent, total_size); 338 | if(scanmap_isempty() && already_sent >= total_size) { 339 | sync_done(true); 340 | } else { 341 | send_dns_data(false); 342 | } 343 | } 344 | else 345 | { 346 | dns_tries++; 347 | if(dns_tries >= MAX_TRIES) { 348 | os_printf("aborting\n"); 349 | dns_tries = 0; 350 | total_size = 0; 351 | already_sent = 0; 352 | dns_frame_id = 0; 353 | sync_done(false); 354 | return; 355 | } 356 | already_sent -= dns_last_send; 357 | os_printf("retrying\n"); 358 | send_dns_data(true); 359 | } 360 | } 361 | } 362 | #endif 363 | 364 | void wifi_callback( System_Event_t *evt ) 365 | { 366 | // os_printf( "%s: %d\n", __FUNCTION__, evt->event ); 367 | 368 | switch ( evt->event ) 369 | { 370 | case EVENT_STAMODE_CONNECTED: 371 | { 372 | // os_printf("connect to ssid %s, channel %d\n", 373 | // evt->event_info.connected.ssid, 374 | // evt->event_info.connected.channel); 375 | break; 376 | } 377 | 378 | case EVENT_STAMODE_DISCONNECTED: 379 | { 380 | // os_printf("disconnect from ssid %s, reason %d\n", 381 | // evt->event_info.disconnected.ssid, 382 | // evt->event_info.disconnected.reason); 383 | break; 384 | } 385 | 386 | case EVENT_STAMODE_GOT_IP: 387 | { 388 | os_timer_disarm(&watchdog_timer); 389 | // os_printf("ip:" IPSTR ",mask:" IPSTR ",gw:" IPSTR, 390 | // IP2STR(&evt->event_info.got_ip.ip), 391 | // IP2STR(&evt->event_info.got_ip.mask), 392 | // IP2STR(&evt->event_info.got_ip.gw)); 393 | // os_printf("\n"); 394 | #ifdef SYNC_HTTP 395 | os_printf("\nHTTP sync\n"); 396 | espconn_gethostbyname( &sync_conn, SYNC_HOST, &sync_ip, dns_done ); 397 | #elif defined(SYNC_DNS) 398 | os_printf("\nDNS sync\n"); 399 | send_dns_data(false); 400 | #else 401 | os_printf("ERROR: no transport protocol\n"); 402 | #endif 403 | break; 404 | } 405 | 406 | default: 407 | { 408 | break; 409 | } 410 | } 411 | } 412 | 413 | void sync_init() { 414 | wifi_set_event_handler_cb( wifi_callback ); 415 | 416 | #ifdef SYNC_SSL 417 | // espconn_secure_ca_disable(0x1); 418 | #endif 419 | 420 | os_timer_disarm(&sync_timer); 421 | os_timer_setfn(&sync_timer, (os_timer_func_t *) sync_cb, NULL); 422 | os_timer_arm(&sync_timer, SYNC_PERIOD, 1); 423 | 424 | os_timer_disarm(&watchdog_timer); 425 | os_timer_setfn(&watchdog_timer, (os_timer_func_t *) watchdog_cb, NULL); 426 | } -------------------------------------------------------------------------------- /user/sync.h: -------------------------------------------------------------------------------- 1 | #ifndef SYNC_H 2 | #define SYNC_H 3 | #include "os_type.h" 4 | 5 | typedef enum { 6 | sync_type_both = 0, 7 | sync_type_time, 8 | sync_type_full, 9 | sync_type_position 10 | } sync_type_t; 11 | 12 | 13 | void sync_init(); 14 | 15 | #ifdef SYNC_HTTP 16 | bool json_put_char(char c); 17 | bool json_put_string(char *s); 18 | #endif 19 | 20 | void sync_sync(); 21 | 22 | #endif -------------------------------------------------------------------------------- /user/uart.c: -------------------------------------------------------------------------------- 1 | /* 2 | * File : uart.c 3 | * Copyright (C) 2013 - 2016, Espressif Systems 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of version 3 of the GNU General Public License as 7 | * published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License along 15 | * with this program. If not, see . 16 | */ 17 | #include "ets_sys.h" 18 | #include "osapi.h" 19 | #include "uart.h" 20 | #include "osapi.h" 21 | #include "uart_register.h" 22 | #include "mem.h" 23 | #include "os_type.h" 24 | 25 | // UartDev is defined and initialized in rom code. 26 | extern UartDevice UartDev; 27 | 28 | LOCAL struct UartBuffer* pTxBuffer = NULL; 29 | LOCAL struct UartBuffer* pRxBuffer = NULL; 30 | 31 | /*uart demo with a system task, to output what uart receives*/ 32 | /*this is a example to process uart data from task,please change the priority to fit your application task if exists*/ 33 | /*it might conflict with your task, if so,please arrange the priority of different task, or combine it to a different event in the same task. */ 34 | #define uart_recvTaskPrio 1 35 | #define uart_recvTaskQueueLen 1 36 | os_event_t uart_recvTaskQueue[uart_recvTaskQueueLen]; 37 | 38 | #define DBG 39 | #define DBG1 uart1_sendStr_no_wait 40 | #define DBG2 os_printf 41 | 42 | 43 | LOCAL void uart0_rx_intr_handler(void *para); 44 | 45 | /****************************************************************************** 46 | * FunctionName : uart_config 47 | * Description : Internal used function 48 | * UART0 used for data TX/RX, RX buffer size is 0x100, interrupt enabled 49 | * UART1 just used for debug output 50 | * Parameters : uart_no, use UART0 or UART1 defined ahead 51 | * Returns : NONE 52 | *******************************************************************************/ 53 | LOCAL void ICACHE_FLASH_ATTR 54 | uart_config(uint8 uart_no) 55 | { 56 | if (uart_no == UART1){ 57 | PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO2_U, FUNC_U1TXD_BK); 58 | }else{ 59 | /* rcv_buff size if 0x100 */ 60 | ETS_UART_INTR_ATTACH(uart0_rx_intr_handler, &(UartDev.rcv_buff)); 61 | PIN_PULLUP_DIS(PERIPHS_IO_MUX_U0TXD_U); 62 | PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0TXD_U, FUNC_U0TXD); 63 | #if UART_HW_RTS 64 | PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, FUNC_U0RTS); //HW FLOW CONTROL RTS PIN 65 | #endif 66 | #if UART_HW_CTS 67 | PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, FUNC_U0CTS); //HW FLOW CONTROL CTS PIN 68 | #endif 69 | } 70 | uart_div_modify(uart_no, UART_CLK_FREQ / (UartDev.baut_rate));//SET BAUDRATE 71 | 72 | WRITE_PERI_REG(UART_CONF0(uart_no), ((UartDev.exist_parity & UART_PARITY_EN_M) << UART_PARITY_EN_S) //SET BIT AND PARITY MODE 73 | | ((UartDev.parity & UART_PARITY_M) <> UART_TXFIFO_CNT_S & UART_TXFIFO_CNT) < 126) { 117 | break; 118 | } 119 | } 120 | WRITE_PERI_REG(UART_FIFO(uart) , TxChar); 121 | return OK; 122 | } 123 | 124 | /****************************************************************************** 125 | * FunctionName : uart1_write_char 126 | * Description : Internal used function 127 | * Do some special deal while tx char is '\r' or '\n' 128 | * Parameters : char c - character to tx 129 | * Returns : NONE 130 | *******************************************************************************/ 131 | LOCAL void ICACHE_FLASH_ATTR 132 | uart1_write_char(char c) 133 | { 134 | if (c == '\n'){ 135 | uart_tx_one_char(UART1, '\r'); 136 | uart_tx_one_char(UART1, '\n'); 137 | }else if (c == '\r'){ 138 | 139 | }else{ 140 | uart_tx_one_char(UART1, c); 141 | } 142 | } 143 | 144 | //os_printf output to fifo or to the tx buffer 145 | LOCAL void ICACHE_FLASH_ATTR 146 | uart0_write_char_no_wait(char c) 147 | { 148 | #if UART_BUFF_EN //send to uart0 fifo but do not wait 149 | uint8 chr; 150 | if (c == '\n'){ 151 | chr = '\r'; 152 | tx_buff_enq(&chr, 1); 153 | chr = '\n'; 154 | tx_buff_enq(&chr, 1); 155 | }else if (c == '\r'){ 156 | 157 | }else{ 158 | tx_buff_enq(&c,1); 159 | } 160 | #else //send to uart tx buffer 161 | if (c == '\n'){ 162 | uart_tx_one_char_no_wait(UART0, '\r'); 163 | uart_tx_one_char_no_wait(UART0, '\n'); 164 | }else if (c == '\r'){ 165 | 166 | } 167 | else{ 168 | uart_tx_one_char_no_wait(UART0, c); 169 | } 170 | #endif 171 | } 172 | 173 | /****************************************************************************** 174 | * FunctionName : uart0_tx_buffer 175 | * Description : use uart0 to transfer buffer 176 | * Parameters : uint8 *buf - point to send buffer 177 | * uint16 len - buffer len 178 | * Returns : 179 | *******************************************************************************/ 180 | void ICACHE_FLASH_ATTR 181 | uart0_tx_buffer(uint8 *buf, uint16 len) 182 | { 183 | uint16 i; 184 | for (i = 0; i < len; i++) 185 | { 186 | uart_tx_one_char(UART0, buf[i]); 187 | } 188 | } 189 | 190 | /****************************************************************************** 191 | * FunctionName : uart0_sendStr 192 | * Description : use uart0 to transfer buffer 193 | * Parameters : uint8 *buf - point to send buffer 194 | * uint16 len - buffer len 195 | * Returns : 196 | *******************************************************************************/ 197 | void ICACHE_FLASH_ATTR 198 | uart0_sendStr(const char *str) 199 | { 200 | while(*str){ 201 | uart_tx_one_char(UART0, *str++); 202 | } 203 | } 204 | void at_port_print(const char *str) __attribute__((alias("uart0_sendStr"))); 205 | /****************************************************************************** 206 | * FunctionName : uart0_rx_intr_handler 207 | * Description : Internal used function 208 | * UART0 interrupt handler, add self handle code inside 209 | * Parameters : void *para - point to ETS_UART_INTR_ATTACH's arg 210 | * Returns : NONE 211 | *******************************************************************************/ 212 | LOCAL void 213 | uart0_rx_intr_handler(void *para) 214 | { 215 | /* uart0 and uart1 intr combine togther, when interrupt occur, see reg 0x3ff20020, bit2, bit0 represents 216 | * uart1 and uart0 respectively 217 | */ 218 | uint8 RcvChar; 219 | uint8 uart_no = UART0;//UartDev.buff_uart_no; 220 | uint8 fifo_len = 0; 221 | uint8 buf_idx = 0; 222 | uint8 temp,cnt; 223 | //RcvMsgBuff *pRxBuff = (RcvMsgBuff *)para; 224 | 225 | /*ATTENTION:*/ 226 | /*IN NON-OS VERSION SDK, DO NOT USE "ICACHE_FLASH_ATTR" FUNCTIONS IN THE WHOLE HANDLER PROCESS*/ 227 | /*ALL THE FUNCTIONS CALLED IN INTERRUPT HANDLER MUST BE DECLARED IN RAM */ 228 | /*IF NOT , POST AN EVENT AND PROCESS IN SYSTEM TASK */ 229 | if(UART_FRM_ERR_INT_ST == (READ_PERI_REG(UART_INT_ST(uart_no)) & UART_FRM_ERR_INT_ST)){ 230 | DBG1("FRM_ERR\r\n"); 231 | WRITE_PERI_REG(UART_INT_CLR(uart_no), UART_FRM_ERR_INT_CLR); 232 | }else if(UART_RXFIFO_FULL_INT_ST == (READ_PERI_REG(UART_INT_ST(uart_no)) & UART_RXFIFO_FULL_INT_ST)){ 233 | DBG("f"); 234 | uart_rx_intr_disable(UART0); 235 | WRITE_PERI_REG(UART_INT_CLR(UART0), UART_RXFIFO_FULL_INT_CLR); 236 | system_os_post(uart_recvTaskPrio, 0, 0); 237 | }else if(UART_RXFIFO_TOUT_INT_ST == (READ_PERI_REG(UART_INT_ST(uart_no)) & UART_RXFIFO_TOUT_INT_ST)){ 238 | DBG("t"); 239 | uart_rx_intr_disable(UART0); 240 | WRITE_PERI_REG(UART_INT_CLR(UART0), UART_RXFIFO_TOUT_INT_CLR); 241 | system_os_post(uart_recvTaskPrio, 0, 0); 242 | 243 | 244 | }else if(UART_TXFIFO_EMPTY_INT_ST == (READ_PERI_REG(UART_INT_ST(uart_no)) & UART_TXFIFO_EMPTY_INT_ST)){ 245 | DBG("e"); 246 | /* to output uart data from uart buffer directly in empty interrupt handler*/ 247 | /*instead of processing in system event, in order not to wait for current task/function to quit */ 248 | /*ATTENTION:*/ 249 | /*IN NON-OS VERSION SDK, DO NOT USE "ICACHE_FLASH_ATTR" FUNCTIONS IN THE WHOLE HANDLER PROCESS*/ 250 | /*ALL THE FUNCTIONS CALLED IN INTERRUPT HANDLER MUST BE DECLARED IN RAM */ 251 | CLEAR_PERI_REG_MASK(UART_INT_ENA(UART0), UART_TXFIFO_EMPTY_INT_ENA); 252 | #if UART_BUFF_EN 253 | tx_start_uart_buffer(UART0); 254 | #endif 255 | //system_os_post(uart_recvTaskPrio, 1, 0); 256 | WRITE_PERI_REG(UART_INT_CLR(uart_no), UART_TXFIFO_EMPTY_INT_CLR); 257 | 258 | }else if(UART_RXFIFO_OVF_INT_ST == (READ_PERI_REG(UART_INT_ST(uart_no)) & UART_RXFIFO_OVF_INT_ST)){ 259 | WRITE_PERI_REG(UART_INT_CLR(uart_no), UART_RXFIFO_OVF_INT_CLR); 260 | DBG1("RX OVF!!\r\n"); 261 | } 262 | 263 | } 264 | 265 | /****************************************************************************** 266 | * FunctionName : uart_init 267 | * Description : user interface for init uart 268 | * Parameters : UartBautRate uart0_br - uart0 bautrate 269 | * UartBautRate uart1_br - uart1 bautrate 270 | * Returns : NONE 271 | *******************************************************************************/ 272 | #if UART_SELFTEST&UART_BUFF_EN 273 | os_timer_t buff_timer_t; 274 | void ICACHE_FLASH_ATTR 275 | uart_test_rx() 276 | { 277 | uint8 uart_buf[128]={0}; 278 | uint16 len = 0; 279 | len = rx_buff_deq(uart_buf, 128 ); 280 | if(len !=0) 281 | tx_buff_enq(uart_buf,len); 282 | } 283 | #endif 284 | 285 | LOCAL void ICACHE_FLASH_ATTR /////// 286 | uart_recvTask(os_event_t *events) 287 | { 288 | if(events->sig == 0){ 289 | #if UART_BUFF_EN 290 | Uart_rx_buff_enq(); 291 | #else 292 | uint8 fifo_len = (READ_PERI_REG(UART_STATUS(UART0))>>UART_RXFIFO_CNT_S)&UART_RXFIFO_CNT; 293 | uint8 d_tmp = 0; 294 | uint8 idx=0; 295 | for(idx=0;idxsig == 1){ 303 | #if UART_BUFF_EN 304 | //already move uart buffer output to uart empty interrupt 305 | //tx_start_uart_buffer(UART0); 306 | #else 307 | 308 | #endif 309 | } 310 | } 311 | 312 | void ICACHE_FLASH_ATTR 313 | uart_init(UartBautRate uart0_br, UartBautRate uart1_br) 314 | { 315 | /*this is a example to process uart data from task,please change the priority to fit your application task if exists*/ 316 | system_os_task(uart_recvTask, uart_recvTaskPrio, uart_recvTaskQueue, uart_recvTaskQueueLen); //demo with a task to process the uart data 317 | 318 | UartDev.baut_rate = uart0_br; 319 | uart_config(UART0); 320 | UartDev.baut_rate = uart1_br; 321 | uart_config(UART1); 322 | ETS_UART_INTR_ENABLE(); 323 | 324 | #if UART_BUFF_EN 325 | pTxBuffer = Uart_Buf_Init(UART_TX_BUFFER_SIZE); 326 | pRxBuffer = Uart_Buf_Init(UART_RX_BUFFER_SIZE); 327 | #endif 328 | 329 | 330 | /*option 1: use default print, output from uart0 , will wait some time if fifo is full */ 331 | //do nothing... 332 | 333 | /*option 2: output from uart1,uart1 output will not wait , just for output debug info */ 334 | /*os_printf output uart data via uart1(GPIO2)*/ 335 | //os_install_putc1((void *)uart1_write_char); //use this one to output debug information via uart1 // 336 | 337 | /*option 3: output from uart0 will skip current byte if fifo is full now... */ 338 | /*see uart0_write_char_no_wait:you can output via a buffer or output directly */ 339 | /*os_printf output uart data via uart0 or uart buffer*/ 340 | //os_install_putc1((void *)uart0_write_char_no_wait); //use this to print via uart0 341 | 342 | #if UART_SELFTEST&UART_BUFF_EN 343 | os_timer_disarm(&buff_timer_t); 344 | os_timer_setfn(&buff_timer_t, uart_test_rx , NULL); //a demo to process the data in uart rx buffer 345 | os_timer_arm(&buff_timer_t,10,1); 346 | #endif 347 | } 348 | 349 | void ICACHE_FLASH_ATTR 350 | uart_reattach() 351 | { 352 | uart_init(BIT_RATE_115200, BIT_RATE_115200); 353 | } 354 | 355 | /****************************************************************************** 356 | * FunctionName : uart_tx_one_char_no_wait 357 | * Description : uart tx a single char without waiting for fifo 358 | * Parameters : uint8 uart - uart port 359 | * uint8 TxChar - char to tx 360 | * Returns : STATUS 361 | *******************************************************************************/ 362 | STATUS uart_tx_one_char_no_wait(uint8 uart, uint8 TxChar) 363 | { 364 | uint8 fifo_cnt = (( READ_PERI_REG(UART_STATUS(uart))>>UART_TXFIFO_CNT_S)& UART_TXFIFO_CNT); 365 | if (fifo_cnt < 126) { 366 | WRITE_PERI_REG(UART_FIFO(uart) , TxChar); 367 | } 368 | return OK; 369 | } 370 | 371 | STATUS uart0_tx_one_char_no_wait(uint8 TxChar) 372 | { 373 | uint8 fifo_cnt = (( READ_PERI_REG(UART_STATUS(UART0))>>UART_TXFIFO_CNT_S)& UART_TXFIFO_CNT); 374 | if (fifo_cnt < 126) { 375 | WRITE_PERI_REG(UART_FIFO(UART0) , TxChar); 376 | } 377 | return OK; 378 | } 379 | 380 | 381 | /****************************************************************************** 382 | * FunctionName : uart1_sendStr_no_wait 383 | * Description : uart tx a string without waiting for every char, used for print debug info which can be lost 384 | * Parameters : const char *str - string to be sent 385 | * Returns : NONE 386 | *******************************************************************************/ 387 | void uart1_sendStr_no_wait(const char *str) 388 | { 389 | while(*str){ 390 | uart_tx_one_char_no_wait(UART1, *str++); 391 | } 392 | } 393 | 394 | 395 | #if UART_BUFF_EN 396 | /****************************************************************************** 397 | * FunctionName : Uart_Buf_Init 398 | * Description : tx buffer enqueue: fill a first linked buffer 399 | * Parameters : char *pdata - data point to be enqueue 400 | * Returns : NONE 401 | *******************************************************************************/ 402 | struct UartBuffer* ICACHE_FLASH_ATTR 403 | Uart_Buf_Init(uint32 buf_size) 404 | { 405 | uint32 heap_size = system_get_free_heap_size(); 406 | if(heap_size <=buf_size){ 407 | DBG1("no buf for uart\n\r"); 408 | return NULL; 409 | }else{ 410 | DBG("test heap size: %d\n\r",heap_size); 411 | struct UartBuffer* pBuff = (struct UartBuffer* )os_malloc(sizeof(struct UartBuffer)); 412 | pBuff->UartBuffSize = buf_size; 413 | pBuff->pUartBuff = (uint8*)os_malloc(pBuff->UartBuffSize); 414 | pBuff->pInPos = pBuff->pUartBuff; 415 | pBuff->pOutPos = pBuff->pUartBuff; 416 | pBuff->Space = pBuff->UartBuffSize; 417 | pBuff->BuffState = OK; 418 | pBuff->nextBuff = NULL; 419 | pBuff->TcpControl = RUN; 420 | return pBuff; 421 | } 422 | } 423 | 424 | 425 | //copy uart buffer 426 | LOCAL void Uart_Buf_Cpy(struct UartBuffer* pCur, char* pdata , uint16 data_len) 427 | { 428 | if(data_len == 0) return ; 429 | 430 | uint16 tail_len = pCur->pUartBuff + pCur->UartBuffSize - pCur->pInPos ; 431 | if(tail_len >= data_len){ //do not need to loop back the queue 432 | os_memcpy(pCur->pInPos , pdata , data_len ); 433 | pCur->pInPos += ( data_len ); 434 | pCur->pInPos = (pCur->pUartBuff + (pCur->pInPos - pCur->pUartBuff) % pCur->UartBuffSize ); 435 | pCur->Space -=data_len; 436 | }else{ 437 | os_memcpy(pCur->pInPos, pdata, tail_len); 438 | pCur->pInPos += ( tail_len ); 439 | pCur->pInPos = (pCur->pUartBuff + (pCur->pInPos - pCur->pUartBuff) % pCur->UartBuffSize ); 440 | pCur->Space -=tail_len; 441 | os_memcpy(pCur->pInPos, pdata+tail_len , data_len-tail_len); 442 | pCur->pInPos += ( data_len-tail_len ); 443 | pCur->pInPos = (pCur->pUartBuff + (pCur->pInPos - pCur->pUartBuff) % pCur->UartBuffSize ); 444 | pCur->Space -=( data_len-tail_len); 445 | } 446 | 447 | } 448 | 449 | /****************************************************************************** 450 | * FunctionName : uart_buf_free 451 | * Description : deinit of the tx buffer 452 | * Parameters : struct UartBuffer* pTxBuff - tx buffer struct pointer 453 | * Returns : NONE 454 | *******************************************************************************/ 455 | void ICACHE_FLASH_ATTR 456 | uart_buf_free(struct UartBuffer* pBuff) 457 | { 458 | os_free(pBuff->pUartBuff); 459 | os_free(pBuff); 460 | } 461 | 462 | 463 | //rx buffer dequeue 464 | uint16 ICACHE_FLASH_ATTR 465 | rx_buff_deq(char* pdata, uint16 data_len ) 466 | { 467 | uint16 buf_len = (pRxBuffer->UartBuffSize- pRxBuffer->Space); 468 | uint16 tail_len = pRxBuffer->pUartBuff + pRxBuffer->UartBuffSize - pRxBuffer->pOutPos ; 469 | uint16 len_tmp = 0; 470 | len_tmp = ((data_len > buf_len)?buf_len:data_len); 471 | if(pRxBuffer->pOutPos <= pRxBuffer->pInPos){ 472 | os_memcpy(pdata, pRxBuffer->pOutPos,len_tmp); 473 | pRxBuffer->pOutPos+= len_tmp; 474 | pRxBuffer->Space += len_tmp; 475 | }else{ 476 | if(len_tmp>tail_len){ 477 | os_memcpy(pdata, pRxBuffer->pOutPos, tail_len); 478 | pRxBuffer->pOutPos += tail_len; 479 | pRxBuffer->pOutPos = (pRxBuffer->pUartBuff + (pRxBuffer->pOutPos- pRxBuffer->pUartBuff) % pRxBuffer->UartBuffSize ); 480 | pRxBuffer->Space += tail_len; 481 | 482 | os_memcpy(pdata+tail_len , pRxBuffer->pOutPos, len_tmp-tail_len); 483 | pRxBuffer->pOutPos+= ( len_tmp-tail_len ); 484 | pRxBuffer->pOutPos= (pRxBuffer->pUartBuff + (pRxBuffer->pOutPos- pRxBuffer->pUartBuff) % pRxBuffer->UartBuffSize ); 485 | pRxBuffer->Space +=( len_tmp-tail_len); 486 | }else{ 487 | //os_printf("case 3 in rx deq\n\r"); 488 | os_memcpy(pdata, pRxBuffer->pOutPos, len_tmp); 489 | pRxBuffer->pOutPos += len_tmp; 490 | pRxBuffer->pOutPos = (pRxBuffer->pUartBuff + (pRxBuffer->pOutPos- pRxBuffer->pUartBuff) % pRxBuffer->UartBuffSize ); 491 | pRxBuffer->Space += len_tmp; 492 | } 493 | } 494 | if(pRxBuffer->Space >= UART_FIFO_LEN){ 495 | uart_rx_intr_enable(UART0); 496 | } 497 | return len_tmp; 498 | } 499 | 500 | 501 | //move data from uart fifo to rx buffer 502 | void Uart_rx_buff_enq() 503 | { 504 | uint8 fifo_len,buf_idx; 505 | uint8 fifo_data; 506 | #if 1 507 | fifo_len = (READ_PERI_REG(UART_STATUS(UART0))>>UART_RXFIFO_CNT_S)&UART_RXFIFO_CNT; 508 | if(fifo_len >= pRxBuffer->Space){ 509 | os_printf("buf full!!!\n\r"); 510 | }else{ 511 | buf_idx=0; 512 | while(buf_idx < fifo_len){ 513 | buf_idx++; 514 | fifo_data = READ_PERI_REG(UART_FIFO(UART0)) & 0xFF; 515 | *(pRxBuffer->pInPos++) = fifo_data; 516 | if(pRxBuffer->pInPos == (pRxBuffer->pUartBuff + pRxBuffer->UartBuffSize)){ 517 | pRxBuffer->pInPos = pRxBuffer->pUartBuff; 518 | } 519 | } 520 | pRxBuffer->Space -= fifo_len ; 521 | if(pRxBuffer->Space >= UART_FIFO_LEN){ 522 | //os_printf("after rx enq buf enough\n\r"); 523 | uart_rx_intr_enable(UART0); 524 | } 525 | } 526 | #endif 527 | } 528 | 529 | 530 | //fill the uart tx buffer 531 | void ICACHE_FLASH_ATTR 532 | tx_buff_enq(char* pdata, uint16 data_len ) 533 | { 534 | CLEAR_PERI_REG_MASK(UART_INT_ENA(UART0), UART_TXFIFO_EMPTY_INT_ENA); 535 | 536 | if(pTxBuffer == NULL){ 537 | DBG1("\n\rnull, create buffer struct\n\r"); 538 | pTxBuffer = Uart_Buf_Init(UART_TX_BUFFER_SIZE); 539 | if(pTxBuffer!= NULL){ 540 | Uart_Buf_Cpy(pTxBuffer , pdata, data_len ); 541 | }else{ 542 | DBG1("uart tx MALLOC no buf \n\r"); 543 | } 544 | }else{ 545 | if(data_len <= pTxBuffer->Space){ 546 | Uart_Buf_Cpy(pTxBuffer , pdata, data_len); 547 | }else{ 548 | DBG1("UART TX BUF FULL!!!!\n\r"); 549 | } 550 | } 551 | #if 0 552 | if(pTxBuffer->Space <= URAT_TX_LOWER_SIZE){ 553 | set_tcp_block(); 554 | } 555 | #endif 556 | SET_PERI_REG_MASK(UART_CONF1(UART0), (UART_TX_EMPTY_THRESH_VAL & UART_TXFIFO_EMPTY_THRHD)<pOutPos++)); 568 | if(pTxBuff->pOutPos == (pTxBuff->pUartBuff + pTxBuff->UartBuffSize)){ 569 | pTxBuff->pOutPos = pTxBuff->pUartBuff; 570 | } 571 | } 572 | pTxBuff->pOutPos = (pTxBuff->pUartBuff + (pTxBuff->pOutPos - pTxBuff->pUartBuff) % pTxBuff->UartBuffSize ); 573 | pTxBuff->Space += data_len; 574 | } 575 | 576 | 577 | /****************************************************************************** 578 | * FunctionName : tx_start_uart_buffer 579 | * Description : get data from the tx buffer and fill the uart tx fifo, co-work with the uart fifo empty interrupt 580 | * Parameters : uint8 uart_no - uart port num 581 | * Returns : NONE 582 | *******************************************************************************/ 583 | void tx_start_uart_buffer(uint8 uart_no) 584 | { 585 | uint8 tx_fifo_len = (READ_PERI_REG(UART_STATUS(uart_no))>>UART_TXFIFO_CNT_S)&UART_TXFIFO_CNT; 586 | uint8 fifo_remain = UART_FIFO_LEN - tx_fifo_len ; 587 | uint8 len_tmp; 588 | uint16 tail_ptx_len,head_ptx_len,data_len; 589 | //struct UartBuffer* pTxBuff = *get_buff_prt(); 590 | 591 | if(pTxBuffer){ 592 | data_len = (pTxBuffer->UartBuffSize - pTxBuffer->Space); 593 | if(data_len > fifo_remain){ 594 | len_tmp = fifo_remain; 595 | tx_fifo_insert( pTxBuffer,len_tmp,uart_no); 596 | SET_PERI_REG_MASK(UART_INT_ENA(UART0), UART_TXFIFO_EMPTY_INT_ENA); 597 | }else{ 598 | len_tmp = data_len; 599 | tx_fifo_insert( pTxBuffer,len_tmp,uart_no); 600 | } 601 | }else{ 602 | DBG1("pTxBuff null \n\r"); 603 | } 604 | } 605 | 606 | #endif 607 | 608 | 609 | void uart_rx_intr_disable(uint8 uart_no) 610 | { 611 | #if 1 612 | CLEAR_PERI_REG_MASK(UART_INT_ENA(uart_no), UART_RXFIFO_FULL_INT_ENA|UART_RXFIFO_TOUT_INT_ENA); 613 | #else 614 | ETS_UART_INTR_DISABLE(); 615 | #endif 616 | } 617 | 618 | void uart_rx_intr_enable(uint8 uart_no) 619 | { 620 | #if 1 621 | SET_PERI_REG_MASK(UART_INT_ENA(uart_no), UART_RXFIFO_FULL_INT_ENA|UART_RXFIFO_TOUT_INT_ENA); 622 | #else 623 | ETS_UART_INTR_ENABLE(); 624 | #endif 625 | } 626 | 627 | 628 | //======================================================== 629 | LOCAL void 630 | uart0_write_char(char c) 631 | { 632 | if (c == '\n') { 633 | uart_tx_one_char(UART0, '\r'); 634 | uart_tx_one_char(UART0, '\n'); 635 | } else if (c == '\r') { 636 | } else { 637 | uart_tx_one_char(UART0, c); 638 | } 639 | } 640 | 641 | void ICACHE_FLASH_ATTR 642 | UART_SetWordLength(uint8 uart_no, UartBitsNum4Char len) 643 | { 644 | SET_PERI_REG_BITS(UART_CONF0(uart_no),UART_BIT_NUM,len,UART_BIT_NUM_S); 645 | } 646 | 647 | void ICACHE_FLASH_ATTR 648 | UART_SetStopBits(uint8 uart_no, UartStopBitsNum bit_num) 649 | { 650 | SET_PERI_REG_BITS(UART_CONF0(uart_no),UART_STOP_BIT_NUM,bit_num,UART_STOP_BIT_NUM_S); 651 | } 652 | 653 | void ICACHE_FLASH_ATTR 654 | UART_SetLineInverse(uint8 uart_no, UART_LineLevelInverse inverse_mask) 655 | { 656 | CLEAR_PERI_REG_MASK(UART_CONF0(uart_no), UART_LINE_INV_MASK); 657 | SET_PERI_REG_MASK(UART_CONF0(uart_no), inverse_mask); 658 | } 659 | 660 | void ICACHE_FLASH_ATTR 661 | UART_SetParity(uint8 uart_no, UartParityMode Parity_mode) 662 | { 663 | CLEAR_PERI_REG_MASK(UART_CONF0(uart_no), UART_PARITY |UART_PARITY_EN); 664 | if(Parity_mode==NONE_BITS){ 665 | }else{ 666 | SET_PERI_REG_MASK(UART_CONF0(uart_no), Parity_mode|UART_PARITY_EN); 667 | } 668 | } 669 | 670 | void ICACHE_FLASH_ATTR 671 | UART_SetBaudrate(uint8 uart_no,uint32 baud_rate) 672 | { 673 | uart_div_modify(uart_no, UART_CLK_FREQ /baud_rate); 674 | } 675 | 676 | void ICACHE_FLASH_ATTR 677 | UART_SetFlowCtrl(uint8 uart_no,UART_HwFlowCtrl flow_ctrl,uint8 rx_thresh) 678 | { 679 | if(flow_ctrl&USART_HardwareFlowControl_RTS){ 680 | PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, FUNC_U0RTS); 681 | SET_PERI_REG_BITS(UART_CONF1(uart_no),UART_RX_FLOW_THRHD,rx_thresh,UART_RX_FLOW_THRHD_S); 682 | SET_PERI_REG_MASK(UART_CONF1(uart_no), UART_RX_FLOW_EN); 683 | }else{ 684 | CLEAR_PERI_REG_MASK(UART_CONF1(uart_no), UART_RX_FLOW_EN); 685 | } 686 | if(flow_ctrl&USART_HardwareFlowControl_CTS){ 687 | PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, FUNC_UART0_CTS); 688 | SET_PERI_REG_MASK(UART_CONF0(uart_no), UART_TX_FLOW_EN); 689 | }else{ 690 | CLEAR_PERI_REG_MASK(UART_CONF0(uart_no), UART_TX_FLOW_EN); 691 | } 692 | } 693 | 694 | void ICACHE_FLASH_ATTR 695 | UART_WaitTxFifoEmpty(uint8 uart_no , uint32 time_out_us) //do not use if tx flow control enabled 696 | { 697 | uint32 t_s = system_get_time(); 698 | while (READ_PERI_REG(UART_STATUS(uart_no)) & (UART_TXFIFO_CNT << UART_TXFIFO_CNT_S)){ 699 | 700 | if(( system_get_time() - t_s )> time_out_us){ 701 | break; 702 | } 703 | WRITE_PERI_REG(0X60000914, 0X73);//WTD 704 | 705 | } 706 | } 707 | 708 | 709 | bool ICACHE_FLASH_ATTR 710 | UART_CheckOutputFinished(uint8 uart_no, uint32 time_out_us) 711 | { 712 | uint32 t_start = system_get_time(); 713 | uint8 tx_fifo_len; 714 | uint32 tx_buff_len; 715 | while(1){ 716 | tx_fifo_len =( (READ_PERI_REG(UART_STATUS(uart_no))>>UART_TXFIFO_CNT_S)&UART_TXFIFO_CNT); 717 | if(pTxBuffer){ 718 | tx_buff_len = ((pTxBuffer->UartBuffSize)-(pTxBuffer->Space)); 719 | }else{ 720 | tx_buff_len = 0; 721 | } 722 | 723 | if( tx_fifo_len==0 && tx_buff_len==0){ 724 | return TRUE; 725 | } 726 | if( system_get_time() - t_start > time_out_us){ 727 | return FALSE; 728 | } 729 | WRITE_PERI_REG(0X60000914, 0X73);//WTD 730 | } 731 | } 732 | 733 | 734 | void ICACHE_FLASH_ATTR 735 | UART_ResetFifo(uint8 uart_no) 736 | { 737 | SET_PERI_REG_MASK(UART_CONF0(uart_no), UART_RXFIFO_RST | UART_TXFIFO_RST); 738 | CLEAR_PERI_REG_MASK(UART_CONF0(uart_no), UART_RXFIFO_RST | UART_TXFIFO_RST); 739 | } 740 | 741 | void ICACHE_FLASH_ATTR 742 | UART_ClearIntrStatus(uint8 uart_no,uint32 clr_mask) 743 | { 744 | WRITE_PERI_REG(UART_INT_CLR(uart_no), clr_mask); 745 | } 746 | 747 | void ICACHE_FLASH_ATTR 748 | UART_SetIntrEna(uint8 uart_no,uint32 ena_mask) 749 | { 750 | SET_PERI_REG_MASK(UART_INT_ENA(uart_no), ena_mask); 751 | } 752 | 753 | 754 | void ICACHE_FLASH_ATTR 755 | UART_SetPrintPort(uint8 uart_no) 756 | { 757 | if(uart_no==1){ 758 | os_install_putc1(uart1_write_char); 759 | }else{ 760 | /*option 1: do not wait if uart fifo is full,drop current character*/ 761 | os_install_putc1(uart0_write_char_no_wait); 762 | /*option 2: wait for a while if uart fifo is full*/ 763 | os_install_putc1(uart0_write_char); 764 | } 765 | } 766 | 767 | 768 | //======================================================== 769 | 770 | 771 | /*test code*/ 772 | void ICACHE_FLASH_ATTR 773 | uart_init_2(UartBautRate uart0_br, UartBautRate uart1_br) 774 | { 775 | // rom use 74880 baut_rate, here reinitialize 776 | UartDev.baut_rate = uart0_br; 777 | UartDev.exist_parity = STICK_PARITY_EN; 778 | UartDev.parity = EVEN_BITS; 779 | UartDev.stop_bits = ONE_STOP_BIT; 780 | UartDev.data_bits = EIGHT_BITS; 781 | 782 | uart_config(UART0); 783 | UartDev.baut_rate = uart1_br; 784 | uart_config(UART1); 785 | ETS_UART_INTR_ENABLE(); 786 | 787 | // install uart1 putc callback 788 | os_install_putc1((void *)uart1_write_char);//print output at UART1 789 | } 790 | 791 | 792 | -------------------------------------------------------------------------------- /user/uart.h: -------------------------------------------------------------------------------- 1 | /* 2 | * File : uart.h 3 | * Copyright (C) 2013 - 2016, Espressif Systems 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of version 3 of the GNU General Public License as 7 | * published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License along 15 | * with this program. If not, see . 16 | */ 17 | #ifndef UART_APP_H 18 | #define UART_APP_H 19 | 20 | #include "uart_register.h" 21 | #include "eagle_soc.h" 22 | #include "c_types.h" 23 | 24 | #define UART_TX_BUFFER_SIZE 256 //Ring buffer length of tx buffer 25 | #define UART_RX_BUFFER_SIZE 256 //Ring buffer length of rx buffer 26 | 27 | #define UART_BUFF_EN 1 //use uart buffer , FOR UART0 28 | #define UART_SELFTEST 0 //set 1:enable the loop test demo for uart buffer, FOR UART0 29 | 30 | #define UART_HW_RTS 0 //set 1: enable uart hw flow control RTS, PIN MTDO, FOR UART0 31 | #define UART_HW_CTS 0 //set1: enable uart hw flow contrl CTS , PIN MTCK, FOR UART0 32 | 33 | 34 | 35 | 36 | #define UART0 0 37 | #define UART1 1 38 | 39 | 40 | typedef enum { 41 | FIVE_BITS = 0x0, 42 | SIX_BITS = 0x1, 43 | SEVEN_BITS = 0x2, 44 | EIGHT_BITS = 0x3 45 | } UartBitsNum4Char; 46 | 47 | typedef enum { 48 | ONE_STOP_BIT = 0x1, 49 | ONE_HALF_STOP_BIT = 0x2, 50 | TWO_STOP_BIT = 0x3 51 | } UartStopBitsNum; 52 | 53 | typedef enum { 54 | NONE_BITS = 0x2, 55 | ODD_BITS = 1, 56 | EVEN_BITS = 0 57 | } UartParityMode; 58 | 59 | typedef enum { 60 | STICK_PARITY_DIS = 0, 61 | STICK_PARITY_EN = 1 62 | } UartExistParity; 63 | 64 | typedef enum { 65 | UART_None_Inverse = 0x0, 66 | UART_Rxd_Inverse = UART_RXD_INV, 67 | UART_CTS_Inverse = UART_CTS_INV, 68 | UART_Txd_Inverse = UART_TXD_INV, 69 | UART_RTS_Inverse = UART_RTS_INV, 70 | } UART_LineLevelInverse; 71 | 72 | 73 | typedef enum { 74 | BIT_RATE_300 = 300, 75 | BIT_RATE_600 = 600, 76 | BIT_RATE_1200 = 1200, 77 | BIT_RATE_2400 = 2400, 78 | BIT_RATE_4800 = 4800, 79 | BIT_RATE_9600 = 9600, 80 | BIT_RATE_19200 = 19200, 81 | BIT_RATE_38400 = 38400, 82 | BIT_RATE_57600 = 57600, 83 | BIT_RATE_74880 = 74880, 84 | BIT_RATE_115200 = 115200, 85 | BIT_RATE_230400 = 230400, 86 | BIT_RATE_460800 = 460800, 87 | BIT_RATE_921600 = 921600, 88 | BIT_RATE_1843200 = 1843200, 89 | BIT_RATE_3686400 = 3686400, 90 | } UartBautRate; 91 | 92 | typedef enum { 93 | NONE_CTRL, 94 | HARDWARE_CTRL, 95 | XON_XOFF_CTRL 96 | } UartFlowCtrl; 97 | 98 | typedef enum { 99 | USART_HardwareFlowControl_None = 0x0, 100 | USART_HardwareFlowControl_RTS = 0x1, 101 | USART_HardwareFlowControl_CTS = 0x2, 102 | USART_HardwareFlowControl_CTS_RTS = 0x3 103 | } UART_HwFlowCtrl; 104 | 105 | typedef enum { 106 | EMPTY, 107 | UNDER_WRITE, 108 | WRITE_OVER 109 | } RcvMsgBuffState; 110 | 111 | typedef struct { 112 | uint32 RcvBuffSize; 113 | uint8 *pRcvMsgBuff; 114 | uint8 *pWritePos; 115 | uint8 *pReadPos; 116 | uint8 TrigLvl; //JLU: may need to pad 117 | RcvMsgBuffState BuffState; 118 | } RcvMsgBuff; 119 | 120 | typedef struct { 121 | uint32 TrxBuffSize; 122 | uint8 *pTrxBuff; 123 | } TrxMsgBuff; 124 | 125 | typedef enum { 126 | BAUD_RATE_DET, 127 | WAIT_SYNC_FRM, 128 | SRCH_MSG_HEAD, 129 | RCV_MSG_BODY, 130 | RCV_ESC_CHAR, 131 | } RcvMsgState; 132 | 133 | typedef struct { 134 | UartBautRate baut_rate; 135 | UartBitsNum4Char data_bits; 136 | UartExistParity exist_parity; 137 | UartParityMode parity; 138 | UartStopBitsNum stop_bits; 139 | UartFlowCtrl flow_ctrl; 140 | RcvMsgBuff rcv_buff; 141 | TrxMsgBuff trx_buff; 142 | RcvMsgState rcv_state; 143 | int received; 144 | int buff_uart_no; //indicate which uart use tx/rx buffer 145 | } UartDevice; 146 | 147 | void uart_init(UartBautRate uart0_br, UartBautRate uart1_br); 148 | void uart0_sendStr(const char *str); 149 | 150 | 151 | /////////////////////////////////////// 152 | #define UART_FIFO_LEN 128 //define the tx fifo length 153 | #define UART_TX_EMPTY_THRESH_VAL 0x10 154 | 155 | 156 | struct UartBuffer{ 157 | uint32 UartBuffSize; 158 | uint8 *pUartBuff; 159 | uint8 *pInPos; 160 | uint8 *pOutPos; 161 | STATUS BuffState; 162 | uint16 Space; //remanent space of the buffer 163 | uint8 TcpControl; 164 | struct UartBuffer * nextBuff; 165 | }; 166 | 167 | struct UartRxBuff{ 168 | uint32 UartRxBuffSize; 169 | uint8 *pUartRxBuff; 170 | uint8 *pWritePos; 171 | uint8 *pReadPos; 172 | STATUS RxBuffState; 173 | uint32 Space; //remanent space of the buffer 174 | } ; 175 | 176 | typedef enum { 177 | RUN = 0, 178 | BLOCK = 1, 179 | } TCPState; 180 | 181 | //void ICACHE_FLASH_ATTR uart_test_rx(); 182 | STATUS uart_tx_one_char(uint8 uart, uint8 TxChar); 183 | STATUS uart_tx_one_char_no_wait(uint8 uart, uint8 TxChar); 184 | void uart1_sendStr_no_wait(const char *str); 185 | struct UartBuffer* Uart_Buf_Init(); 186 | 187 | 188 | #if UART_BUFF_EN 189 | LOCAL void Uart_Buf_Cpy(struct UartBuffer* pCur, char* pdata , uint16 data_len); 190 | void uart_buf_free(struct UartBuffer* pBuff); 191 | void tx_buff_enq(char* pdata, uint16 data_len ); 192 | LOCAL void tx_fifo_insert(struct UartBuffer* pTxBuff, uint8 data_len, uint8 uart_no); 193 | void tx_start_uart_buffer(uint8 uart_no); 194 | uint16 rx_buff_deq(char* pdata, uint16 data_len ); 195 | void Uart_rx_buff_enq(); 196 | #endif 197 | void uart_rx_intr_enable(uint8 uart_no); 198 | void uart_rx_intr_disable(uint8 uart_no); 199 | void uart0_tx_buffer(uint8 *buf, uint16 len); 200 | 201 | //============================================== 202 | #define FUNC_UART0_CTS 4 203 | #define FUNC_U0CTS 4 204 | #define FUNC_U1TXD_BK 2 205 | #define UART_LINE_INV_MASK (0x3f<<19) 206 | void UART_SetWordLength(uint8 uart_no, UartBitsNum4Char len); 207 | void UART_SetStopBits(uint8 uart_no, UartStopBitsNum bit_num); 208 | void UART_SetLineInverse(uint8 uart_no, UART_LineLevelInverse inverse_mask); 209 | void UART_SetParity(uint8 uart_no, UartParityMode Parity_mode); 210 | void UART_SetBaudrate(uint8 uart_no,uint32 baud_rate); 211 | void UART_SetFlowCtrl(uint8 uart_no,UART_HwFlowCtrl flow_ctrl,uint8 rx_thresh); 212 | void UART_WaitTxFifoEmpty(uint8 uart_no , uint32 time_out_us); //do not use if tx flow control enabled 213 | void UART_ResetFifo(uint8 uart_no); 214 | void UART_ClearIntrStatus(uint8 uart_no,uint32 clr_mask); 215 | void UART_SetIntrEna(uint8 uart_no,uint32 ena_mask); 216 | void UART_SetPrintPort(uint8 uart_no); 217 | bool UART_CheckOutputFinished(uint8 uart_no, uint32 time_out_us); 218 | //============================================== 219 | 220 | #endif 221 | 222 | -------------------------------------------------------------------------------- /user/uart_register.h: -------------------------------------------------------------------------------- 1 | /* 2 | * File : uart_register.h 3 | * Copyright (C) 2013 - 2016, Espressif Systems 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of version 3 of the GNU General Public License as 7 | * published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License along 15 | * with this program. If not, see . 16 | */ 17 | /* 18 | * Copyright (c) 2010 - 2011 Espressif System 19 | * 20 | */ 21 | 22 | #ifndef UART_REGISTER_H_ 23 | #define UART_REGISTER_H_ 24 | 25 | #define REG_UART_BASE(i) (0x60000000 + (i)*0xf00) 26 | //version value:32'h062000 27 | 28 | #define UART_FIFO(i) (REG_UART_BASE(i) + 0x0) 29 | #define UART_RXFIFO_RD_BYTE 0x000000FF 30 | #define UART_RXFIFO_RD_BYTE_S 0 31 | 32 | #define UART_INT_RAW(i) (REG_UART_BASE(i) + 0x4) 33 | #define UART_RXFIFO_TOUT_INT_RAW (BIT(8)) 34 | #define UART_BRK_DET_INT_RAW (BIT(7)) 35 | #define UART_CTS_CHG_INT_RAW (BIT(6)) 36 | #define UART_DSR_CHG_INT_RAW (BIT(5)) 37 | #define UART_RXFIFO_OVF_INT_RAW (BIT(4)) 38 | #define UART_FRM_ERR_INT_RAW (BIT(3)) 39 | #define UART_PARITY_ERR_INT_RAW (BIT(2)) 40 | #define UART_TXFIFO_EMPTY_INT_RAW (BIT(1)) 41 | #define UART_RXFIFO_FULL_INT_RAW (BIT(0)) 42 | 43 | #define UART_INT_ST(i) (REG_UART_BASE(i) + 0x8) 44 | #define UART_RXFIFO_TOUT_INT_ST (BIT(8)) 45 | #define UART_BRK_DET_INT_ST (BIT(7)) 46 | #define UART_CTS_CHG_INT_ST (BIT(6)) 47 | #define UART_DSR_CHG_INT_ST (BIT(5)) 48 | #define UART_RXFIFO_OVF_INT_ST (BIT(4)) 49 | #define UART_FRM_ERR_INT_ST (BIT(3)) 50 | #define UART_PARITY_ERR_INT_ST (BIT(2)) 51 | #define UART_TXFIFO_EMPTY_INT_ST (BIT(1)) 52 | #define UART_RXFIFO_FULL_INT_ST (BIT(0)) 53 | 54 | #define UART_INT_ENA(i) (REG_UART_BASE(i) + 0xC) 55 | #define UART_RXFIFO_TOUT_INT_ENA (BIT(8)) 56 | #define UART_BRK_DET_INT_ENA (BIT(7)) 57 | #define UART_CTS_CHG_INT_ENA (BIT(6)) 58 | #define UART_DSR_CHG_INT_ENA (BIT(5)) 59 | #define UART_RXFIFO_OVF_INT_ENA (BIT(4)) 60 | #define UART_FRM_ERR_INT_ENA (BIT(3)) 61 | #define UART_PARITY_ERR_INT_ENA (BIT(2)) 62 | #define UART_TXFIFO_EMPTY_INT_ENA (BIT(1)) 63 | #define UART_RXFIFO_FULL_INT_ENA (BIT(0)) 64 | 65 | #define UART_INT_CLR(i) (REG_UART_BASE(i) + 0x10) 66 | #define UART_RXFIFO_TOUT_INT_CLR (BIT(8)) 67 | #define UART_BRK_DET_INT_CLR (BIT(7)) 68 | #define UART_CTS_CHG_INT_CLR (BIT(6)) 69 | #define UART_DSR_CHG_INT_CLR (BIT(5)) 70 | #define UART_RXFIFO_OVF_INT_CLR (BIT(4)) 71 | #define UART_FRM_ERR_INT_CLR (BIT(3)) 72 | #define UART_PARITY_ERR_INT_CLR (BIT(2)) 73 | #define UART_TXFIFO_EMPTY_INT_CLR (BIT(1)) 74 | #define UART_RXFIFO_FULL_INT_CLR (BIT(0)) 75 | 76 | #define UART_CLKDIV(i) (REG_UART_BASE(i) + 0x14) 77 | #define UART_CLKDIV_CNT 0x000FFFFF 78 | #define UART_CLKDIV_S 0 79 | 80 | #define UART_AUTOBAUD(i) (REG_UART_BASE(i) + 0x18) 81 | #define UART_GLITCH_FILT 0x000000FF 82 | #define UART_GLITCH_FILT_S 8 83 | #define UART_AUTOBAUD_EN (BIT(0)) 84 | 85 | #define UART_STATUS(i) (REG_UART_BASE(i) + 0x1C) 86 | #define UART_TXD (BIT(31)) 87 | #define UART_RTSN (BIT(30)) 88 | #define UART_DTRN (BIT(29)) 89 | #define UART_TXFIFO_CNT 0x000000FF 90 | #define UART_TXFIFO_CNT_S 16 91 | #define UART_RXD (BIT(15)) 92 | #define UART_CTSN (BIT(14)) 93 | #define UART_DSRN (BIT(13)) 94 | #define UART_RXFIFO_CNT 0x000000FF 95 | #define UART_RXFIFO_CNT_S 0 96 | 97 | #define UART_CONF0(i) (REG_UART_BASE(i) + 0x20) 98 | #define UART_DTR_INV (BIT(24)) 99 | #define UART_RTS_INV (BIT(23)) 100 | #define UART_TXD_INV (BIT(22)) 101 | #define UART_DSR_INV (BIT(21)) 102 | #define UART_CTS_INV (BIT(20)) 103 | #define UART_RXD_INV (BIT(19)) 104 | #define UART_TXFIFO_RST (BIT(18)) 105 | #define UART_RXFIFO_RST (BIT(17)) 106 | #define UART_IRDA_EN (BIT(16)) 107 | #define UART_TX_FLOW_EN (BIT(15)) 108 | #define UART_LOOPBACK (BIT(14)) 109 | #define UART_IRDA_RX_INV (BIT(13)) 110 | #define UART_IRDA_TX_INV (BIT(12)) 111 | #define UART_IRDA_WCTL (BIT(11)) 112 | #define UART_IRDA_TX_EN (BIT(10)) 113 | #define UART_IRDA_DPLX (BIT(9)) 114 | #define UART_TXD_BRK (BIT(8)) 115 | #define UART_SW_DTR (BIT(7)) 116 | #define UART_SW_RTS (BIT(6)) 117 | #define UART_STOP_BIT_NUM 0x00000003 118 | #define UART_STOP_BIT_NUM_S 4 119 | #define UART_BIT_NUM 0x00000003 120 | #define UART_BIT_NUM_S 2 121 | #define UART_PARITY_EN (BIT(1)) 122 | #define UART_PARITY_EN_M 0x00000001 123 | #define UART_PARITY_EN_S 1 124 | #define UART_PARITY (BIT(0)) 125 | #define UART_PARITY_M 0x00000001 126 | #define UART_PARITY_S 0 127 | 128 | #define UART_CONF1(i) (REG_UART_BASE(i) + 0x24) 129 | #define UART_RX_TOUT_EN (BIT(31)) 130 | #define UART_RX_TOUT_THRHD 0x0000007F 131 | #define UART_RX_TOUT_THRHD_S 24 132 | #define UART_RX_FLOW_EN (BIT(23)) 133 | #define UART_RX_FLOW_THRHD 0x0000007F 134 | #define UART_RX_FLOW_THRHD_S 16 135 | #define UART_TXFIFO_EMPTY_THRHD 0x0000007F 136 | #define UART_TXFIFO_EMPTY_THRHD_S 8 137 | #define UART_RXFIFO_FULL_THRHD 0x0000007F 138 | #define UART_RXFIFO_FULL_THRHD_S 0 139 | 140 | #define UART_LOWPULSE(i) (REG_UART_BASE(i) + 0x28) 141 | #define UART_LOWPULSE_MIN_CNT 0x000FFFFF 142 | #define UART_LOWPULSE_MIN_CNT_S 0 143 | 144 | #define UART_HIGHPULSE(i) (REG_UART_BASE(i) + 0x2C) 145 | #define UART_HIGHPULSE_MIN_CNT 0x000FFFFF 146 | #define UART_HIGHPULSE_MIN_CNT_S 0 147 | 148 | #define UART_PULSE_NUM(i) (REG_UART_BASE(i) + 0x30) 149 | #define UART_PULSE_NUM_CNT 0x0003FF 150 | #define UART_PULSE_NUM_CNT_S 0 151 | 152 | #define UART_DATE(i) (REG_UART_BASE(i) + 0x78) 153 | #define UART_ID(i) (REG_UART_BASE(i) + 0x7C) 154 | 155 | #endif // UART_REGISTER_H_INCLUDED 156 | 157 | -------------------------------------------------------------------------------- /user/upg.c: -------------------------------------------------------------------------------- 1 | #ifdef USE_OTA 2 | 3 | #include "upg.h" 4 | 5 | #include "upgrade.h" 6 | #include "user_interface.h" 7 | #include "ip_addr.h" 8 | #include "ets_sys.h" 9 | #include "osapi.h" 10 | #include "espconn.h" 11 | #include 12 | 13 | 14 | static void ICACHE_FLASH_ATTR ota_finished_callback(void *arg) 15 | { 16 | struct upgrade_server_info *update = (struct upgrade_server_info *)arg; 17 | if (update->upgrade_flag == true) 18 | { 19 | os_printf("[OTA]success; rebooting!\n"); 20 | system_upgrade_reboot(); 21 | } 22 | else 23 | { 24 | os_printf("[OTA]failed!\n"); 25 | } 26 | 27 | os_free(update->pespconn); 28 | os_free(update->url); 29 | os_free(update); 30 | } 31 | 32 | bool ICACHE_FLASH_ATTR handleUpgrade(uint8_t serverVersion, const char *server_ip, uint16_t port, const char *path) 33 | { 34 | const char* file; 35 | uint8_t userBin = system_upgrade_userbin_check(); 36 | switch (userBin) 37 | { 38 | case UPGRADE_FW_BIN1: file = "user2.bin"; break; 39 | case UPGRADE_FW_BIN2: file = "user1.bin"; break; 40 | default: 41 | os_printf("[OTA]Invalid userbin number!\n"); 42 | return false; 43 | } 44 | 45 | uint16_t version=1; 46 | if (serverVersion <= version) 47 | { 48 | os_printf("[OTA]No update. Server version:%d, local version %d\n", serverVersion, version); 49 | return false; 50 | } 51 | 52 | os_printf("[OTA]Upgrade available version: %d\n", serverVersion); 53 | 54 | struct upgrade_server_info* update = (struct upgrade_server_info *)os_zalloc(sizeof(struct upgrade_server_info)); 55 | update->pespconn = (struct espconn *)os_zalloc(sizeof(struct espconn)); 56 | 57 | update->ip[0] = 192; 58 | update->ip[1] = 168; 59 | update->ip[2] = 211; 60 | update->ip[3] = 145; 61 | // os_memcpy(update->ip, server_ip, 4); 62 | update->port = port; 63 | 64 | os_printf("[OTA]Server "IPSTR":%d. Path: %s\n", IP2STR(update->ip), update->port, path); 65 | 66 | update->check_cb = ota_finished_callback; 67 | update->check_times = 120000; 68 | update->url = (uint8 *)os_zalloc(512); 69 | 70 | os_sprintf((char*)update->url, 71 | "GET %s HTTP/1.1\r\n" 72 | "Host: "IPSTR":%d\r\n" 73 | "Connection: close\r\n" 74 | "\r\n", 75 | path, IP2STR(update->ip), update->port); 76 | os_printf(update->url); 77 | system_upgrade_flag_set(0x00); 78 | if (system_upgrade_start(update) == false) 79 | { 80 | os_printf("[OTA]Could not start upgrade\n"); 81 | 82 | os_free(update->pespconn); 83 | os_free(update->url); 84 | os_free(update); 85 | return false; 86 | } 87 | else 88 | { 89 | os_printf("[OTA]Upgrading...\n"); 90 | return true; 91 | } 92 | } 93 | 94 | #endif -------------------------------------------------------------------------------- /user/upg.h: -------------------------------------------------------------------------------- 1 | #ifdef USE_OTA 2 | 3 | #ifndef UPGRADE_H 4 | #define UPGRADE_H 5 | #include "user_interface.h" 6 | 7 | bool ICACHE_FLASH_ATTR handleUpgrade(uint8_t serverVersion, const char *server_ip, uint16_t port, const char *path); 8 | 9 | #endif 10 | 11 | #endif -------------------------------------------------------------------------------- /user/user_config.h: -------------------------------------------------------------------------------- 1 | #ifndef USER_CONFIG_HPP 2 | #define USER_CONFIG_HPP 3 | 4 | 5 | #define ETH_MAC_LEN 6 6 | #define MAX_APS_TRACKED 20 7 | #define MAX_CLIENTS_TRACKED 0 8 | #define MAX_PROBES_TRACKED 0 9 | 10 | #define CHANNEL_HOP_INTERVAL 100 11 | 12 | 13 | // #define PRINT_ELEMENTS 1 14 | 15 | //2hours 16 | #define CLIENT_MAX_TIME 60*60*2 17 | 18 | #define SYNC_HOST "t1.lauters.fr" 19 | // #define SYNC_HOST "wifis.lauters.fr" 20 | // #define SYNC_PORT 8686 21 | // #define SYNC_PATH "/esp8266.json" 22 | #define SYNC_MIN_LEVEL -75 23 | // #define SYNC_SSL 24 | 25 | // sync data through dns tunneling 26 | #define SYNC_DNS 27 | 28 | #ifndef SYNC_DNS 29 | # define SYNC_HTTP 30 | #endif 31 | 32 | #include "os_type.h" 33 | 34 | // used with sync_type_position will ensure that there will be at least X access point on the fifo 35 | #define MIN_SYNCING_BEST_AP 5 36 | 37 | #define SYNC_TYPE sync_type_position 38 | 39 | //millis 40 | #define SYNC_PERIOD 1*60*1000 41 | 42 | #define MAX_TRIES 1 43 | 44 | // uncomment to use over the air upgrade 45 | // #define USE_OTA 46 | 47 | // uncomment to toggle at each registered entity (beacon, probe, client...) 48 | // #define LED_TOGGLE_REGISTER 49 | 50 | // have a look to wifis_spots.h to configure your wifis access 51 | 52 | 53 | uint32_t get_seconds(); 54 | 55 | void toggle_led(); 56 | void blink_led(int count, int delay); 57 | void set_led(bool _status); 58 | uint32_t get_button_pressed(); 59 | 60 | #endif -------------------------------------------------------------------------------- /user/user_json.c: -------------------------------------------------------------------------------- 1 | #include "user_json.h" 2 | #include 3 | #include "osapi.h" 4 | #include "sync.h" 5 | 6 | #define os_realloc pvPortRealloc 7 | void *pvPortRealloc(void* ptr, size_t size); 8 | 9 | #define MAX_SMALL_BUFFER_SIZE 255 10 | 11 | 12 | #define os_sprintf ets_sprintf 13 | 14 | char * printmac(char *_out, uint8_t *buf) { 15 | os_sprintf(_out, "%02X:%02X:%02X:%02X:%02X:%02X", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]); 16 | return _out; 17 | } 18 | 19 | bool build_probe_json(struct probeinfo pi, bool second) { 20 | if(pi.err) { 21 | return true; 22 | } 23 | char buf [MAX_SMALL_BUFFER_SIZE]; 24 | os_memset(buf, 0, MAX_SMALL_BUFFER_SIZE); 25 | char mac[17]; 26 | printmac(mac, pi.bssid); 27 | if(second) { 28 | os_sprintf(buf, ","); 29 | } 30 | os_sprintf(buf, "%s{\"t\":\"%d\",\"b\":\"%s\",\"e\":\"%s\"}", buf, pi.time_s, mac, pi.ssid); 31 | return json_put_string(buf); 32 | } 33 | 34 | bool build_beacon_json(struct beaconinfo bi, bool second) { 35 | if(bi.err) { 36 | return true; 37 | } 38 | char buf [MAX_SMALL_BUFFER_SIZE]; 39 | os_memset(buf, 0, MAX_SMALL_BUFFER_SIZE); 40 | char mac[17]; 41 | printmac(mac, bi.bssid); 42 | if(second) { 43 | os_sprintf(buf, ","); 44 | } 45 | os_sprintf(buf, "%s{\"t\":\"%d\",\"b\":\"%s\",\"e\":\"%s\", \"c\":\"%d\", \"s\":\"%d\", \"k\":%d}", buf, bi.time_s, mac, bi.ssid, bi.channel, bi.rssi, bi.encryption); 46 | return json_put_string(buf); 47 | } 48 | 49 | bool build_client_json(struct clientinfo ci, bool second) { 50 | if(ci.err) { 51 | return true; 52 | } 53 | char buf[MAX_SMALL_BUFFER_SIZE]; 54 | os_memset(buf, 0, MAX_SMALL_BUFFER_SIZE); 55 | char mac[17]; 56 | printmac(mac, ci.bssid); 57 | if(second) { 58 | os_sprintf(buf, ","); 59 | } 60 | os_sprintf(buf, "%s{\"t\":\"%d\",\"b\":\"%s\", \"s\":%d}",buf,ci.time_s, mac, ci.rssi); 61 | return json_put_string(buf); 62 | } 63 | 64 | void build_beacons_json(fifo_t *_beacons) { 65 | json_put_char('['); 66 | uint16_t i = 0; 67 | while(!fifo_isempty(_beacons)) { 68 | bool res; 69 | if(i == 0){ 70 | res = build_beacon_json(fifo_pop(_beacons).beaconinfo,false); 71 | } else { 72 | res = build_beacon_json(fifo_pop(_beacons).beaconinfo, true); 73 | } 74 | 75 | if(!res) { 76 | break; 77 | } 78 | 79 | i++; 80 | } 81 | json_put_char(']'); 82 | } 83 | 84 | void build_probes_json(fifo_t *_probes) { 85 | json_put_char('['); 86 | uint16_t i = 0; 87 | while(!fifo_isempty(_probes)) { 88 | bool res; 89 | if(i == 0){ 90 | res = build_probe_json(fifo_pop(_probes).probeinfo, false); 91 | } else { 92 | res = build_probe_json(fifo_pop(_probes).probeinfo, true); 93 | } 94 | 95 | if(!res) { 96 | break; 97 | } 98 | 99 | i++; 100 | } 101 | json_put_char(']'); 102 | } 103 | 104 | void build_clients_json(fifo_t *_clients) { 105 | json_put_char('['); 106 | uint16_t i = 0; 107 | while(!fifo_isempty(_clients)) { 108 | bool res; 109 | if(i == 0){ 110 | res = build_client_json(fifo_pop(_clients).clientinfo,false); 111 | } else { 112 | res = build_client_json(fifo_pop(_clients).clientinfo, true); 113 | } 114 | 115 | if(!res) { 116 | break; 117 | } 118 | 119 | i++; 120 | } 121 | json_put_char(']'); 122 | } 123 | 124 | void build_json(struct data *_data) { 125 | char tmp[MAX_SMALL_BUFFER_SIZE]; 126 | os_sprintf(tmp, "{\"n\":\"esp8266_%d\",",system_get_chip_id()); 127 | json_put_string(tmp); 128 | json_put_string("\"p\":"); 129 | build_probes_json(&_data->probesinfos); 130 | if(json_put_string(",\"ap\":")) { 131 | build_beacons_json(&_data->beaconsinfos); 132 | } 133 | if( json_put_string(",\"s\":") ) { 134 | build_clients_json(&_data->clientsinfos); 135 | } 136 | json_put_char('}'); 137 | } -------------------------------------------------------------------------------- /user/user_json.h: -------------------------------------------------------------------------------- 1 | #ifndef USER_JSON_HPP 2 | #define USER_JSON_HPP 3 | #include "scanmap.h" 4 | 5 | void build_json(struct data *_data); 6 | 7 | #endif -------------------------------------------------------------------------------- /user/user_main.c: -------------------------------------------------------------------------------- 1 | #include "ets_sys.h" 2 | #include "osapi.h" 3 | #include "gpio.h" 4 | #include "user_config.h" 5 | #include "user_json.h" 6 | #include "scanmap.h" 7 | #include "sync.h" 8 | #include "uart.h" 9 | 10 | #include "user_interface.h" 11 | 12 | 13 | #define user_procTaskPrio 0 14 | #define user_procTaskQueueLen 1 15 | 16 | os_event_t user_procTaskQueue[user_procTaskQueueLen]; 17 | static void user_procTask(os_event_t *events); 18 | 19 | static volatile os_timer_t second_timer; 20 | 21 | static volatile os_timer_t blink_timer; 22 | 23 | volatile uint32_t seconds = 0; 24 | int blink_count = 0; 25 | int blink_delay = 0; // ms 26 | 27 | void user_rf_pre_init(void) { 28 | } 29 | 30 | 31 | void second_cb(void *arg) { 32 | //TODO LOCK 33 | seconds ++; 34 | } 35 | 36 | uint32_t get_seconds() { 37 | return seconds; 38 | } 39 | 40 | uint32_t get_button_pressed() { 41 | return GPIO_INPUT_GET(0) == 0; 42 | } 43 | 44 | void set_led(bool _status) { 45 | if(_status) { 46 | //Set GPIO2 to LOW 47 | gpio_output_set(0, BIT2, BIT2, 0); 48 | } else { 49 | //Set GPIO2 to HIGH 50 | gpio_output_set(BIT2, 0, BIT2, 0); 51 | } 52 | } 53 | 54 | void toggle_led() { 55 | 56 | if(get_button_pressed()) { 57 | return; // button pressed 58 | } 59 | //Do blinky stuff 60 | if (GPIO_REG_READ(GPIO_OUT_ADDRESS) & BIT2) 61 | { 62 | set_led(true); 63 | } 64 | else 65 | { 66 | set_led(false); 67 | } 68 | } 69 | 70 | void blink_once_led_next(void *arg) { 71 | blink_led(blink_count -1, blink_delay); 72 | } 73 | 74 | void blink_once_led_done(void *arg) 75 | { 76 | os_timer_disarm(&blink_timer); 77 | set_led(false); 78 | if(blink_count > 0) { 79 | os_timer_setfn(&blink_timer, (os_timer_func_t *) blink_once_led_next, NULL); 80 | os_timer_arm(&blink_timer, blink_delay, 1); 81 | } 82 | } 83 | 84 | void blink_led(int count, int delay) { 85 | os_timer_setfn(&blink_timer, (os_timer_func_t *) blink_once_led_done, NULL); 86 | os_timer_arm(&blink_timer, delay, 1); 87 | blink_count = count; 88 | blink_delay = delay; 89 | set_led(true); 90 | } 91 | 92 | void hex_print(char *p, size_t n) 93 | { 94 | char HEX[]="0123456789ABCDEF"; 95 | unsigned int i,j,count; 96 | j=0; 97 | i=0; 98 | count=0; 99 | while(j < n) 100 | { 101 | count++; 102 | os_printf("0x%02x\t",count); 103 | if(j+16> 4],HEX[p[j+i]&0xF]); 107 | } 108 | os_printf("\t"); 109 | for(i=0;i<16;i++) 110 | { 111 | os_printf("%c",isprint(p[j+i])?p[j+i]:'.'); 112 | } 113 | os_printf("\n"); 114 | j = j+16; 115 | } 116 | else 117 | { 118 | for(i=0;i> 4],HEX[p[j+i]&0xF]); 121 | } 122 | os_printf("\t"); 123 | for(i=0;i