ESP32學(xué)習(xí)筆記(5)——WiFi接口使用(STA和AP模式)

一舔示、概述

Wi-Fi 庫支持配置及監(jiān)控 ESP32 Wi-Fi 連網(wǎng)功能借杰。

支持配置:

  • 基站模式(即 STA 模式或 Wi-Fi 客戶端模式)过吻,此時 ESP32 連接到接入點 (AP)。


  • AP 模式(即 Soft-AP 模式或接入點模式),此時基站連接到 ESP32纤虽。


  • AP-STA 共存模式(ESP32 既是接入點乳绕,同時又作為基站連接到另外一個接入點)。

  • 上述模式的各種安全模式(WPA逼纸、WPA2 及 WEP 等)洋措。

  • 掃描接入點(包括主動掃描及被動掃描)。

  • 使用混雜模式監(jiān)控 IEEE802.11 Wi-Fi 數(shù)據(jù)包杰刽。

ESP-IDF 編程指南——Wi-Fi

二菠发、API說明

以下 WIFI 接口位于 esp_wifi/include/esp_wifi.h

2.1 esp_wifi_init

2.2 esp_wifi_set_mode

2.3 esp_wifi_get_mode

2.4 esp_wifi_start

2.5 esp_wifi_connect

2.6 esp_wifi_disconnect

2.7 esp_wifi_scan_start

2.8 esp_wifi_get_mac

2.9 esp_wifi_set_config

2.10 esp_wifi_get_config

三贺嫂、AP模式

3.1 一般場景

3.2 Wi-Fi/LwIP初始階段

如上圖中 1.1\1.2\1.3\1.4 所示滓鸠,分別

  • 初始化LwIP
    創(chuàng)建LwIP核心任務(wù)并初始化與LwIP相關(guān)的工作。
ESP_ERROR_CHECK(esp_netif_init());
  • 初始化Wi-Fi事件處理
    Wi-Fi事件處理基于esp_event庫第喳。Wi-Fi驅(qū)動程序會將事件發(fā)送到默認事件循環(huán)糜俗。應(yīng)用程序可以在使用進行注冊的回調(diào)中處理這些事件esp_event_handler_register()esp_netif組件還處理Wi-Fi事件曲饱,以提供一組默認行為悠抹。例如,當(dāng)Wi-Fi站連接到AP時渔工,esp_netif將自動啟動DHCP客戶端(默認情況下)锌钮。
// 創(chuàng)建系統(tǒng)事件任務(wù)并初始化應(yīng)用程序事件的回調(diào)函數(shù)。
ESP_ERROR_CHECK(esp_event_loop_create_default());
// 創(chuàng)建具有TCP / IP堆棧的默認網(wǎng)絡(luò)接口實例綁定AP引矩。
esp_netif_create_default_wifi_ap();

ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT,
                                                    ESP_EVENT_ANY_ID,
                                                    &wifi_event_handler,
                                                    NULL,
                                                    NULL));
  • 初始化Wi-Fi
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_wifi_init(&cfg));

3.3 Wi-Fi配置階段

wifi_config_t wifi_config = {
        .ap = {
            .ssid = EXAMPLE_ESP_WIFI_SSID,
            .ssid_len = strlen(EXAMPLE_ESP_WIFI_SSID),
            .channel = EXAMPLE_ESP_WIFI_CHANNEL,
            .password = EXAMPLE_ESP_WIFI_PASS,
            .max_connection = EXAMPLE_MAX_STA_CONN,
            .authmode = WIFI_AUTH_WPA_WPA2_PSK
        },
    };
    if (strlen(EXAMPLE_ESP_WIFI_PASS) == 0) {
        wifi_config.ap.authmode = WIFI_AUTH_OPEN;
    }

    ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_AP));
    ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_AP, &wifi_config));

3.4 Wi-Fi啟動階段

ESP_ERROR_CHECK(esp_wifi_start());

3.5 Wi-Fi連接階段

當(dāng)有終端接入或斷開連接時,產(chǎn)生 WIFI_EVENT_AP_STACONNECTEDWIFI_EVENT_AP_STADISCONNECTED 事件侵浸。

static void wifi_event_handler(void* arg, esp_event_base_t event_base,
                                    int32_t event_id, void* event_data)
{
    if (event_id == WIFI_EVENT_AP_STACONNECTED) {
        wifi_event_ap_staconnected_t* event = (wifi_event_ap_staconnected_t*) event_data;
        ESP_LOGI(TAG, "station "MACSTR" join, AID=%d",
                 MAC2STR(event->mac), event->aid);
    } else if (event_id == WIFI_EVENT_AP_STADISCONNECTED) {
        wifi_event_ap_stadisconnected_t* event = (wifi_event_ap_stadisconnected_t*) event_data;
        ESP_LOGI(TAG, "station "MACSTR" leave, AID=%d",
                 MAC2STR(event->mac), event->aid);
    }
}

3.6 完整代碼

/*  WiFi softAP Example

   This example code is in the Public Domain (or CC0 licensed, at your option.)

   Unless required by applicable law or agreed to in writing, this
   software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
   CONDITIONS OF ANY KIND, either express or implied.
*/
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "esp_wifi.h"
#include "esp_event.h"
#include "esp_log.h"
#include "nvs_flash.h"

#include "lwip/err.h"
#include "lwip/sys.h"

/* The examples use WiFi configuration that you can set via project configuration menu.

   If you'd rather not, just change the below entries to strings with
   the config you want - ie #define EXAMPLE_WIFI_SSID "mywifissid"
*/
#define EXAMPLE_ESP_WIFI_SSID      CONFIG_ESP_WIFI_SSID
#define EXAMPLE_ESP_WIFI_PASS      CONFIG_ESP_WIFI_PASSWORD
#define EXAMPLE_ESP_WIFI_CHANNEL   CONFIG_ESP_WIFI_CHANNEL
#define EXAMPLE_MAX_STA_CONN       CONFIG_ESP_MAX_STA_CONN

static const char *TAG = "wifi softAP";

static void wifi_event_handler(void* arg, esp_event_base_t event_base,
                                    int32_t event_id, void* event_data)
{
    if (event_id == WIFI_EVENT_AP_STACONNECTED) {
        wifi_event_ap_staconnected_t* event = (wifi_event_ap_staconnected_t*) event_data;
        ESP_LOGI(TAG, "station "MACSTR" join, AID=%d",
                 MAC2STR(event->mac), event->aid);
    } else if (event_id == WIFI_EVENT_AP_STADISCONNECTED) {
        wifi_event_ap_stadisconnected_t* event = (wifi_event_ap_stadisconnected_t*) event_data;
        ESP_LOGI(TAG, "station "MACSTR" leave, AID=%d",
                 MAC2STR(event->mac), event->aid);
    }
}

void wifi_init_softap(void)
{
    ESP_ERROR_CHECK(esp_netif_init());
    ESP_ERROR_CHECK(esp_event_loop_create_default());
    esp_netif_create_default_wifi_ap();

    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
    ESP_ERROR_CHECK(esp_wifi_init(&cfg));

    ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT,
                                                        ESP_EVENT_ANY_ID,
                                                        &wifi_event_handler,
                                                        NULL,
                                                        NULL));

    wifi_config_t wifi_config = {
        .ap = {
            .ssid = EXAMPLE_ESP_WIFI_SSID,
            .ssid_len = strlen(EXAMPLE_ESP_WIFI_SSID),
            .channel = EXAMPLE_ESP_WIFI_CHANNEL,
            .password = EXAMPLE_ESP_WIFI_PASS,
            .max_connection = EXAMPLE_MAX_STA_CONN,
            .authmode = WIFI_AUTH_WPA_WPA2_PSK
        },
    };
    if (strlen(EXAMPLE_ESP_WIFI_PASS) == 0) {
        wifi_config.ap.authmode = WIFI_AUTH_OPEN;
    }

    ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_AP));
    ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_AP, &wifi_config));
    ESP_ERROR_CHECK(esp_wifi_start());

    ESP_LOGI(TAG, "wifi_init_softap finished. SSID:%s password:%s channel:%d",
             EXAMPLE_ESP_WIFI_SSID, EXAMPLE_ESP_WIFI_PASS, EXAMPLE_ESP_WIFI_CHANNEL);
}

void app_main(void)
{
    //Initialize NVS
    esp_err_t ret = nvs_flash_init();
    if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
      ESP_ERROR_CHECK(nvs_flash_erase());
      ret = nvs_flash_init();
    }
    ESP_ERROR_CHECK(ret);

    ESP_LOGI(TAG, "ESP_WIFI_MODE_AP");
    wifi_init_softap();
}

四旺韭、STA模式

4.1 一般場景

4.2 Wi-Fi/LwIP初始階段

如上圖中 1.1\1.2\1.3\1.4 所示,分別

  • 初始化LwIP
    創(chuàng)建LwIP核心任務(wù)并初始化與LwIP相關(guān)的工作掏觉。
ESP_ERROR_CHECK(esp_netif_init());
  • 初始化Wi-Fi事件處理
    Wi-Fi事件處理基于esp_event庫区端。Wi-Fi驅(qū)動程序會將事件發(fā)送到默認事件循環(huán)。應(yīng)用程序可以在使用進行注冊的回調(diào)中處理這些事件esp_event_handler_register()澳腹。esp_netif組件還處理Wi-Fi事件织盼,以提供一組默認行為。例如酱塔,當(dāng)Wi-Fi站連接到AP時沥邻,esp_netif將自動啟動DHCP客戶端(默認情況下)。
// 創(chuàng)建系統(tǒng)事件任務(wù)并初始化應(yīng)用程序事件的回調(diào)函數(shù)羊娃。
ESP_ERROR_CHECK(esp_event_loop_create_default());
// 創(chuàng)建具有TCP / IP堆棧的默認網(wǎng)絡(luò)接口實例綁定基站唐全。
esp_netif_create_default_wifi_sta();

esp_event_handler_instance_t instance_any_id;
esp_event_handler_instance_t instance_got_ip;
ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT,
                                                    ESP_EVENT_ANY_ID,
                                                    &event_handler,
                                                    NULL,
                                                    &instance_any_id));
ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT,
                                                    IP_EVENT_STA_GOT_IP,
                                                    &event_handler,
                                                    NULL,
                                                    instance_got_ip));
  • 初始化Wi-Fi
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_wifi_init(&cfg));

4.3 Wi-Fi配置階段

wifi_config_t wifi_config = {
        .sta = {
            .ssid = EXAMPLE_ESP_WIFI_SSID,
            .password = EXAMPLE_ESP_WIFI_PASS,
            /* Setting a password implies station will connect to all security modes including WEP/WPA.
             * However these modes are deprecated and not advisable to be used. Incase your Access point
             * doesn't support WPA2, these mode can be enabled by commenting below line */
            .threshold.authmode = WIFI_AUTH_WPA2_PSK,

            .pmf_cfg = {
                .capable = true,
                .required = false
            },
        },
    };
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA) );
ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config) );

4.4 Wi-Fi啟動階段

調(diào)用esp_wifi_start()以啟動Wi-Fi驅(qū)動程序排苍。

Wi-Fi驅(qū)動程序?qū)?a target="_blank">WIFI_EVENT_STA_START發(fā)布到事件任務(wù);然后珊泳,事件任務(wù)將執(zhí)行一些常規(guī)操作缺猛,并將調(diào)用應(yīng)用程序事件回調(diào)函數(shù)。

應(yīng)用程序事件回調(diào)函數(shù)將WIFI_EVENT_STA_START中繼到應(yīng)用程序任務(wù)延届。此時調(diào)用esp_wifi_connect()剪勿。

ESP_ERROR_CHECK(esp_wifi_start());

4.5 Wi-Fi連接階段

一旦esp_wifi_connect()被調(diào)用,Wi-Fi驅(qū)動程序?qū)㈤_始內(nèi)部掃描/連接過程方庭。

如果內(nèi)部掃描/連接過程成功厕吉,將生成WIFI_EVENT_STA_CONNECTED。在事件任務(wù)中二鳄,它將啟動DHCP客戶端赴涵,該客戶端最終將觸發(fā)DHCP進程。

由于例如密碼錯誤订讼,找不到AP等原因髓窜,Wi-Fi連接可能會失敗。在這種情況下欺殿,會出現(xiàn)WIFI_EVENT_STA_DISCONNECTED并提供這種失敗的原因寄纵。

static void event_handler(void* arg, esp_event_base_t event_base,
                                int32_t event_id, void* event_data)
{
    if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) {
        esp_wifi_connect();
    } else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {
        if (s_retry_num < EXAMPLE_ESP_MAXIMUM_RETRY) {
            esp_wifi_connect();
            s_retry_num++;
            ESP_LOGI(TAG, "retry to connect to the AP");
        } else {
            xEventGroupSetBits(s_wifi_event_group, WIFI_FAIL_BIT);
        }
        ESP_LOGI(TAG,"connect to the AP fail");
    } else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
        ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data;
        ESP_LOGI(TAG, "got ip:" IPSTR, IP2STR(&event->ip_info.ip));
        s_retry_num = 0;
        xEventGroupSetBits(s_wifi_event_group, WIFI_CONNECTED_BIT);
    }
}

4.6 Wi-Fi“Got IP”階段

初始化DHCP客戶端后,將開始IP階段脖苏。如果從DHCP服務(wù)器成功接收到IP地址程拭,則將出現(xiàn)IP_EVENT_STA_GOT_IP,并且事件任務(wù)將執(zhí)行常規(guī)處理棍潘。

在應(yīng)用程序事件回調(diào)中恃鞋,IP_EVENT_STA_GOT_IP被中繼到應(yīng)用程序任務(wù)。對于基于LwIP的應(yīng)用程序亦歉,此事件非常特殊恤浪,這意味著該應(yīng)用程序已準備就緒,可以開始其任務(wù)肴楷,例如創(chuàng)建TCP / UDP套接字等水由。一個非常常見的錯誤是在收到IP_EVENT_STA_GOT_IP之前初始化套接字。接收IP之前赛蔫,請勿開始與套接字相關(guān)的工作砂客。

五、掃描

當(dāng)前呵恢,esp_wifi_scan_start()僅在Station或Station + AP模式下支持該API鞠值。

掃描所有頻道后,將出現(xiàn)WIFI_EVENT_SCAN_DONE瑰剃。

應(yīng)用程序的事件回調(diào)函數(shù)通知應(yīng)用程序任務(wù)已接收到WIFI_EVENT_SCAN_DONE齿诉。esp_wifi_scan_get_ap_num()調(diào)用以獲取在此掃描中找到的AP的數(shù)量。然后,它分配足夠的條目和調(diào)用esp_wifi_scan_get_ap_records()以獲取AP記錄粤剧。請注意歇竟,一旦esp_wifi_scan_get_ap_records()被調(diào)用,Wi-Fi驅(qū)動程序中的AP記錄將被釋放抵恋。esp_wifi_scan_get_ap_records()一次掃描完成事件請勿調(diào)用兩次焕议。如果esp_wifi_scan_get_ap_records()在發(fā)生掃描完成事件時未調(diào)用,則不會釋放由Wi-Fi驅(qū)動程序分配的AP記錄弧关。因此盅安,請確保調(diào)用esp_wifi_scan_get_ap_records(),但只能調(diào)用一次世囊。

/* Scan Example

   This example code is in the Public Domain (or CC0 licensed, at your option.)

   Unless required by applicable law or agreed to in writing, this
   software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
   CONDITIONS OF ANY KIND, either express or implied.
*/

/*
    This example shows how to scan for available set of APs.
*/
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/event_groups.h"
#include "esp_wifi.h"
#include "esp_log.h"
#include "esp_event.h"
#include "nvs_flash.h"

#define DEFAULT_SCAN_LIST_SIZE CONFIG_EXAMPLE_SCAN_LIST_SIZE

static const char *TAG = "scan";

static void print_auth_mode(int authmode)
{
    switch (authmode) {
    case WIFI_AUTH_OPEN:
        ESP_LOGI(TAG, "Authmode \tWIFI_AUTH_OPEN");
        break;
    case WIFI_AUTH_WEP:
        ESP_LOGI(TAG, "Authmode \tWIFI_AUTH_WEP");
        break;
    case WIFI_AUTH_WPA_PSK:
        ESP_LOGI(TAG, "Authmode \tWIFI_AUTH_WPA_PSK");
        break;
    case WIFI_AUTH_WPA2_PSK:
        ESP_LOGI(TAG, "Authmode \tWIFI_AUTH_WPA2_PSK");
        break;
    case WIFI_AUTH_WPA_WPA2_PSK:
        ESP_LOGI(TAG, "Authmode \tWIFI_AUTH_WPA_WPA2_PSK");
        break;
    case WIFI_AUTH_WPA2_ENTERPRISE:
        ESP_LOGI(TAG, "Authmode \tWIFI_AUTH_WPA2_ENTERPRISE");
        break;
    case WIFI_AUTH_WPA3_PSK:
        ESP_LOGI(TAG, "Authmode \tWIFI_AUTH_WPA3_PSK");
        break;
    case WIFI_AUTH_WPA2_WPA3_PSK:
        ESP_LOGI(TAG, "Authmode \tWIFI_AUTH_WPA2_WPA3_PSK");
        break;
    default:
        ESP_LOGI(TAG, "Authmode \tWIFI_AUTH_UNKNOWN");
        break;
    }
}

static void print_cipher_type(int pairwise_cipher, int group_cipher)
{
    switch (pairwise_cipher) {
    case WIFI_CIPHER_TYPE_NONE:
        ESP_LOGI(TAG, "Pairwise Cipher \tWIFI_CIPHER_TYPE_NONE");
        break;
    case WIFI_CIPHER_TYPE_WEP40:
        ESP_LOGI(TAG, "Pairwise Cipher \tWIFI_CIPHER_TYPE_WEP40");
        break;
    case WIFI_CIPHER_TYPE_WEP104:
        ESP_LOGI(TAG, "Pairwise Cipher \tWIFI_CIPHER_TYPE_WEP104");
        break;
    case WIFI_CIPHER_TYPE_TKIP:
        ESP_LOGI(TAG, "Pairwise Cipher \tWIFI_CIPHER_TYPE_TKIP");
        break;
    case WIFI_CIPHER_TYPE_CCMP:
        ESP_LOGI(TAG, "Pairwise Cipher \tWIFI_CIPHER_TYPE_CCMP");
        break;
    case WIFI_CIPHER_TYPE_TKIP_CCMP:
        ESP_LOGI(TAG, "Pairwise Cipher \tWIFI_CIPHER_TYPE_TKIP_CCMP");
        break;
    default:
        ESP_LOGI(TAG, "Pairwise Cipher \tWIFI_CIPHER_TYPE_UNKNOWN");
        break;
    }

    switch (group_cipher) {
    case WIFI_CIPHER_TYPE_NONE:
        ESP_LOGI(TAG, "Group Cipher \tWIFI_CIPHER_TYPE_NONE");
        break;
    case WIFI_CIPHER_TYPE_WEP40:
        ESP_LOGI(TAG, "Group Cipher \tWIFI_CIPHER_TYPE_WEP40");
        break;
    case WIFI_CIPHER_TYPE_WEP104:
        ESP_LOGI(TAG, "Group Cipher \tWIFI_CIPHER_TYPE_WEP104");
        break;
    case WIFI_CIPHER_TYPE_TKIP:
        ESP_LOGI(TAG, "Group Cipher \tWIFI_CIPHER_TYPE_TKIP");
        break;
    case WIFI_CIPHER_TYPE_CCMP:
        ESP_LOGI(TAG, "Group Cipher \tWIFI_CIPHER_TYPE_CCMP");
        break;
    case WIFI_CIPHER_TYPE_TKIP_CCMP:
        ESP_LOGI(TAG, "Group Cipher \tWIFI_CIPHER_TYPE_TKIP_CCMP");
        break;
    default:
        ESP_LOGI(TAG, "Group Cipher \tWIFI_CIPHER_TYPE_UNKNOWN");
        break;
    }
}

/* Initialize Wi-Fi as sta and set scan method */
static void wifi_scan(void)
{
    ESP_ERROR_CHECK(esp_netif_init());
    ESP_ERROR_CHECK(esp_event_loop_create_default());
    esp_netif_t *sta_netif = esp_netif_create_default_wifi_sta();
    assert(sta_netif);

    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
    ESP_ERROR_CHECK(esp_wifi_init(&cfg));

    uint16_t number = DEFAULT_SCAN_LIST_SIZE;
    wifi_ap_record_t ap_info[DEFAULT_SCAN_LIST_SIZE];
    uint16_t ap_count = 0;
    memset(ap_info, 0, sizeof(ap_info));

    ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
    ESP_ERROR_CHECK(esp_wifi_start());
    ESP_ERROR_CHECK(esp_wifi_scan_start(NULL, true));
    ESP_ERROR_CHECK(esp_wifi_scan_get_ap_records(&number, ap_info));
    ESP_ERROR_CHECK(esp_wifi_scan_get_ap_num(&ap_count));
    ESP_LOGI(TAG, "Total APs scanned = %u", ap_count);
    for (int i = 0; (i < DEFAULT_SCAN_LIST_SIZE) && (i < ap_count); i++) {
        ESP_LOGI(TAG, "SSID \t\t%s", ap_info[i].ssid);
        ESP_LOGI(TAG, "RSSI \t\t%d", ap_info[i].rssi);
        print_auth_mode(ap_info[i].authmode);
        if (ap_info[i].authmode != WIFI_AUTH_WEP) {
            print_cipher_type(ap_info[i].pairwise_cipher, ap_info[i].group_cipher);
        }
        ESP_LOGI(TAG, "Channel \t\t%d\n", ap_info[i].primary);
    }

}

void app_main(void)
{
    // Initialize NVS
    esp_err_t ret = nvs_flash_init();
    if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
        ESP_ERROR_CHECK(nvs_flash_erase());
        ret = nvs_flash_init();
    }
    ESP_ERROR_CHECK( ret );

    wifi_scan();
}

? 由 Leung 寫于 2021 年 4 月 19 日

? 參考:Wi-Fi驅(qū)動程序
    ESP32 開發(fā)筆記(三)源碼示例 19_WIFI_STA 創(chuàng)建STA站模式連接路由器
    ESP32 開發(fā)筆記(三)源碼示例 15_WIFI_AP 創(chuàng)建軟AP示例
    ESP32 開發(fā)筆記(三)源碼示例 14_WIFI_Scan 附近WIFI信號掃描示例

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末别瞭,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子株憾,更是在濱河造成了極大的恐慌蝙寨,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,214評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件嗤瞎,死亡現(xiàn)場離奇詭異墙歪,居然都是意外死亡,警方通過查閱死者的電腦和手機贝奇,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評論 2 382
  • 文/潘曉璐 我一進店門虹菲,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人掉瞳,你說我怎么就攤上這事毕源。” “怎么了陕习?”我有些...
    開封第一講書人閱讀 152,543評論 0 341
  • 文/不壞的土叔 我叫張陵脑豹,是天一觀的道長。 經(jīng)常有香客問我衡查,道長,這世上最難降的妖魔是什么必盖? 我笑而不...
    開封第一講書人閱讀 55,221評論 1 279
  • 正文 為了忘掉前任拌牲,我火速辦了婚禮,結(jié)果婚禮上歌粥,老公的妹妹穿的比我還像新娘塌忽。我一直安慰自己,他們只是感情好失驶,可當(dāng)我...
    茶點故事閱讀 64,224評論 5 371
  • 文/花漫 我一把揭開白布土居。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪擦耀。 梳的紋絲不亂的頭發(fā)上棉圈,一...
    開封第一講書人閱讀 49,007評論 1 284
  • 那天,我揣著相機與錄音眷蜓,去河邊找鬼分瘾。 笑死,一個胖子當(dāng)著我的面吹牛吁系,可吹牛的內(nèi)容都是我干的德召。 我是一名探鬼主播,決...
    沈念sama閱讀 38,313評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼汽纤,長吁一口氣:“原來是場噩夢啊……” “哼上岗!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起蕴坪,我...
    開封第一講書人閱讀 36,956評論 0 259
  • 序言:老撾萬榮一對情侶失蹤肴掷,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后辞嗡,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體捆等,經(jīng)...
    沈念sama閱讀 43,441評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,925評論 2 323
  • 正文 我和宋清朗相戀三年续室,在試婚紗的時候發(fā)現(xiàn)自己被綠了栋烤。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,018評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡挺狰,死狀恐怖明郭,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情丰泊,我是刑警寧澤薯定,帶...
    沈念sama閱讀 33,685評論 4 322
  • 正文 年R本政府宣布,位于F島的核電站瞳购,受9級特大地震影響话侄,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜学赛,卻給世界環(huán)境...
    茶點故事閱讀 39,234評論 3 307
  • 文/蒙蒙 一年堆、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧盏浇,春花似錦变丧、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽童擎。三九已至,卻和暖如春攻晒,著一層夾襖步出監(jiān)牢的瞬間顾复,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評論 1 261
  • 我被黑心中介騙來泰國打工炎辨, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留捕透,地道東北人。 一個月前我還...
    沈念sama閱讀 45,467評論 2 352
  • 正文 我出身青樓碴萧,卻偏偏與公主長得像乙嘀,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子破喻,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,762評論 2 345

推薦閱讀更多精彩內(nèi)容