玩轉 ESP32 + Arduino(三十) onenet5.0 全新MQTT設備連接體驗

一. 體驗新版更新內容

onenet5.0是一個大改版, 連用了多年的LOGO都換掉了, 現(xiàn)在的logo更簡約美觀了

1. OneNET Studio

更新后推出了一個OneNET Studio 的概念, 所有接入服務放在了這里面

進入 OneNET Studio 發(fā)現(xiàn)其整合相當一部分的業(yè)務, 而且分的非常明晰

2. 設備接入

現(xiàn)在, 我們關心的主要內容是設備接入

3. 產品管理和創(chuàng)建產品

產品管理界面簡介美觀

添加產品很容易

這里有了第一個概念 OneJson

4. OneJson概念

OneJson 就是OneNet能自動解析的JSON, 如果你按照這個格式上傳json數(shù)據(jù), 會省略上傳數(shù)據(jù)解析過程.

參考文檔: https://open.iot.10086.cn/doc/iot_platform/book/device-connect&manager/thing-model/protocol/OneJSON/OneJSON-introduce.html

5. 創(chuàng)建物模型

創(chuàng)建完產品后, 要開始創(chuàng)建物模型

  • 更新后的onenet MQTT和阿里云IOT一樣擁有了物模型的概念

關于物模型, 請參考以下文檔:

https://open.iot.10086.cn/doc/iot_platform/book/device-connect&manager/thing-model/introduce.html

創(chuàng)建物模型分為 系統(tǒng)功能點 和 自定義功能點組

5.1 系統(tǒng)功能點(如果不需要定位服務,可以忽略此節(jié))

目前只有兩個

這個功能點已經完全定死, 我們只能提交符合它的格式的數(shù)據(jù),

根據(jù)官方的SDK, 其結構如下:

5.2 自定義功能點組

自定義功能點分為3類

很容易明白這三類的意思, 本次試驗我們只用屬性類

創(chuàng)建功能點很簡單:

和阿里云IOT一樣, 創(chuàng)建完保存才能更新

6. 添加設備

添加設備還是那么的無腦 ??我喜歡

添加完設備后, 我們就得到了設備的關鍵信息了!!!

7. 計算token

和之前一樣, 參考文章: http://www.reibang.com/p/1c8dccc35b61
或者看文檔: https://open.iot.10086.cn/doc/iot_platform/book/device-connect&manager/device-auth.html

通過 產品ID 設備名 和token 我們就可以接入新版OneNet了

8. 接入地址

和之前不一樣了
參考文檔: https://open.iot.10086.cn/doc/iot_platform/book/device-connect&manager/MQTT/mqtt-device-development.html

現(xiàn)在我們要接入的是: 218.201.45.7 : 1883 了!!

9. 通訊主題

原先OneNet可以說只有兩個主題 , 現(xiàn)在終于把主題的概念發(fā)展開了, 越看越像阿里IOT了

參考文檔 : https://open.iot.10086.cn/doc/iot_platform/book/device-connect&manager/MQTT/topic.html

10. 新版MQTT通訊限制

文檔把通訊限制寫的非常明確, 這很好!
https://open.iot.10086.cn/doc/iot_platform/book/device-connect&manager/MQTT/mqtt-limit.html

二. 上傳溫濕度至新版ONENET示例

#include <Arduino.h>
#include "WiFi.h"
#include "PubSubClient.h"
#include "Ticker.h"
#include "uFire_SHT20.h"

uFire_SHT20 sht20;

const char *ssid = "anleng";              //wifi名
const char *password = "al77776666";      //wifi密碼
const char *mqtt_server = "218.201.45.7"; //onenet 的 IP地址
const int port = 1883;                    //端口號

#define mqtt_pubid "IaiJ9078ZN"    //產品ID
#define mqtt_devid "esp_mqtts_001" //設備名稱
//鑒權信息
#define mqtt_password "version=2018-10-31&res=products%2FIaiJ9078ZN%2Fdevices%2Fesp_mqtts_001&et=4092599349&method=md5&sign=nvhmyIawpRbUyAojvL8CRA%3D%3D" //鑒權信息

WiFiClient espClient;           //創(chuàng)建一個WIFI連接客戶端
PubSubClient client(espClient); // 創(chuàng)建一個PubSub客戶端, 傳入創(chuàng)建的WIFI客戶端
Ticker tim1;                    //定時器,用來循環(huán)上傳數(shù)據(jù)
//設備下發(fā)命令的set主題
#define ONENET_TOPIC_PROP_SET "$sys/" mqtt_pubid "/" mqtt_devid "/thing/property/set"
//設備上傳數(shù)據(jù)的post主題
#define ONENET_TOPIC_PROP_POST "$sys/" mqtt_pubid "/" mqtt_devid "/thing/property/post"

//這是post上傳數(shù)據(jù)使用的模板
#define ONENET_POST_BODY_FORMAT "{\"id\":\"%u\",\"params\":%s}"
int postMsgId = 0; //記錄已經post了多少條

//連接WIFI相關函數(shù)
void setupWifi()
{
  delay(10);
  Serial.println("connect WIFI");
  WiFi.begin(ssid, password);
  while (!WiFi.isConnected())
  {
    Serial.print(".");
    delay(500);
  }
  Serial.println("OK");
  Serial.println("Wifi connected!");
}

//向主題發(fā)送模擬的溫濕度數(shù)據(jù)
void sendTempAndHumi()
{
  if (client.connected())
  {
    //先拼接出json字符串
    char param[82];
    char jsonBuf[178];
    sprintf(param, "{\"temp\":{\"value\":%.2f},\"humi\":{\"value\":%.2f}}", sht20.temperature(), sht20.humidity()); //我們把要上傳的數(shù)據(jù)寫在param里
    postMsgId += 1;
    sprintf(jsonBuf, ONENET_POST_BODY_FORMAT, postMsgId, param);
    //再從mqtt客戶端中發(fā)布post消息
    if (client.publish(ONENET_TOPIC_PROP_POST, jsonBuf))
    {
      Serial.print("Post message to cloud: ");
      Serial.println(jsonBuf);
    }
    else
    {
      Serial.println("Publish message to cloud failed!");
    }
  }
}

//重連函數(shù), 如果客戶端斷線,可以通過此函數(shù)重連
void clientReconnect()
{
  while (!client.connected()) //再重連客戶端
  {
    Serial.println("reconnect MQTT...");
    if (client.connect(mqtt_devid, mqtt_pubid, mqtt_password))
    {
      Serial.println("connected");
    }
    else
    {
      Serial.println("failed");
      Serial.println(client.state());
      Serial.println("try again in 5 sec");
      delay(5000);
    }
  }
}

void setup()
{
  Serial.begin(115200); //初始化串口
  Wire.begin();
  sht20.begin();
  delay(3000);                                           //這個延時是為了讓我打開串口助手
  setupWifi();                                           //調用函數(shù)連接WIFI
  client.setServer(mqtt_server, port);                   //設置客戶端連接的服務器,連接Onenet服務器, 使用6002端口
  client.connect(mqtt_devid, mqtt_pubid, mqtt_password); //客戶端連接到指定的產品的指定設備.同時輸入鑒權信息
  if (client.connected())
  {
    Serial.println("OneNet is connected!"); //判斷以下是不是連好了.
  }
  tim1.attach(10, sendTempAndHumi); //定時每10秒調用一次發(fā)送數(shù)據(jù)函數(shù)sendTempAndHumi
}

void loop()
{
  if (!WiFi.isConnected()) //先看WIFI是否還在連接
  {
    setupWifi();
  }
  if (!client.connected()) //如果客戶端沒連接ONENET, 重新連接
  {
    clientReconnect();
    delay(100);
  }
  client.loop(); //客戶端循環(huán)檢測
}

三. 下面的版本更全面,配合onenet5.0 API調用的章節(jié)

參考文章:

http://www.reibang.com/p/902a73b4a758
http://www.reibang.com/p/cdf03171346e
http://www.reibang.com/p/c5bb7a63b4cb

#include <Arduino.h>
#include "WiFi.h"
#include "PubSubClient.h"
#include "Ticker.h"
#include "uFire_SHT20.h"
#include "ArduinoJson.h"

uFire_SHT20 sht20;

const char *ssid = "anleng";              //wifi名
const char *password = "al77776666";      //wifi密碼
const char *mqtt_server = "218.201.45.7"; //onenet 的 IP地址
const int port = 1883;                    //端口號

#define mqtt_pubid "IaiJ9078ZN"    //產品ID
#define mqtt_devid "esp_mqtts_001" //設備名稱
//鑒權信息
#define mqtt_password "version=2018-10-31&res=products%2FIaiJ9078ZN%2Fdevices%2Fesp_mqtts_001&et=4092599349&method=md5&sign=nvhmyIawpRbUyAojvL8CRA%3D%3D" //鑒權信息

WiFiClient espClient;           //創(chuàng)建一個WIFI連接客戶端
PubSubClient client(espClient); // 創(chuàng)建一個PubSub客戶端, 傳入創(chuàng)建的WIFI客戶端
Ticker tim1;                    //定時器,用來循環(huán)上傳數(shù)據(jù)
float temp;
float humi;

//設備上傳數(shù)據(jù)的post主題
#define ONENET_TOPIC_PROP_POST "$sys/" mqtt_pubid "/" mqtt_devid "/thing/property/post"
//接收下發(fā)屬性設置主題
#define ONENET_TOPIC_PROP_SET "$sys/" mqtt_pubid "/" mqtt_devid "/thing/property/set"
//接收下發(fā)屬性設置成功的回復主題
#define ONENET_TOPIC_PROP_SET_REPLY "$sys/" mqtt_pubid "/" mqtt_devid "/thing/property/set_reply"

//接收設備屬性獲取命令主題
#define ONENET_TOPIC_PROP_GET "$sys/" mqtt_pubid "/" mqtt_devid "/thing/property/get"
//接收設備屬性獲取命令成功的回復主題
#define ONENET_TOPIC_PROP_GET_REPLY "$sys/" mqtt_pubid "/" mqtt_devid "/thing/property/get_reply"

//這是post上傳數(shù)據(jù)使用的模板
#define ONENET_POST_BODY_FORMAT "{\"id\":\"%u\",\"params\":%s}"
int postMsgId = 0; //記錄已經post了多少條

//連接WIFI相關函數(shù)
void setupWifi()
{
  delay(10);
  Serial.println("connect WIFI");
  WiFi.begin(ssid, password);
  while (!WiFi.isConnected())
  {
    Serial.print(".");
    delay(500);
  }
  Serial.println("OK");
  Serial.println("Wifi connected!");
}

//向主題發(fā)送模擬的溫濕度數(shù)據(jù)
void sendTempAndHumi()
{
  if (client.connected())
  {
    //先拼接出json字符串
    char param[82];
    char jsonBuf[178];
    sprintf(param, "{\"temp\":{\"value\":%.2f},\"humi\":{\"value\":%.2f}}", temp, humi); //我們把要上傳的數(shù)據(jù)寫在param里
    postMsgId += 1;
    sprintf(jsonBuf, ONENET_POST_BODY_FORMAT, postMsgId, param);
    //再從mqtt客戶端中發(fā)布post消息
    if (client.publish(ONENET_TOPIC_PROP_POST, jsonBuf))
    {
      Serial.print("Post message to cloud: ");
      Serial.println(jsonBuf);
    }
    else
    {
      Serial.println("Publish message to cloud failed!");
    }
  }
}

//重連函數(shù), 如果客戶端斷線,可以通過此函數(shù)重連
void clientReconnect()
{
  while (!client.connected()) //再重連客戶端
  {
    Serial.println("reconnect MQTT...");
    if (client.connect(mqtt_devid, mqtt_pubid, mqtt_password))
    {
      Serial.println("connected");
    }
    else
    {
      Serial.println("failed");
      Serial.println(client.state());
      Serial.println("try again in 5 sec");
      delay(5000);
    }
  }
}

void callback(char *topic, byte *payload, unsigned int length)
{
  Serial.println("message rev:");
  Serial.println(topic);
  for (size_t i = 0; i < length; i++)
  {
    Serial.print((char)payload[i]);
  }
  Serial.println();

  if (strstr(topic, ONENET_TOPIC_PROP_SET))
  {
    DynamicJsonDocument doc(100);
    DeserializationError error = deserializeJson(doc, payload);
    if (error)
    {
      Serial.println("parse json failed");
      return;
    }
    JsonObject setAlinkMsgObj = doc.as<JsonObject>();
    serializeJsonPretty(setAlinkMsgObj, Serial);
    String str = setAlinkMsgObj["id"];
    Serial.println(str);
    char sendbuf[100];
    sprintf(sendbuf, "{\"id\": \"%s\",\"code\":200,\"msg\":\"success\"}", str.c_str());
    Serial.println(sendbuf);
    client.publish(ONENET_TOPIC_PROP_SET_REPLY, sendbuf);
  }
  if (strstr(topic, ONENET_TOPIC_PROP_GET))
  {
    DynamicJsonDocument doc(100);
    DeserializationError error = deserializeJson(doc, payload);
    if (error)
    {
      Serial.println("parse json failed");
      return;
    }
    JsonObject setAlinkMsgObj = doc.as<JsonObject>();
    serializeJsonPretty(setAlinkMsgObj, Serial);
    String str = setAlinkMsgObj["id"];
    Serial.println(str);
    char sendbuf[100];
    sprintf(sendbuf, "{\"id\": \"%s\",\"code\":200,\"msg\":\"success\",\"data\":{\"temp\":%.2f,\"humi\":%.2f}}", str.c_str(), sht20.temperature(), sht20.humidity());
    Serial.println(sendbuf);
    client.publish(ONENET_TOPIC_PROP_GET_REPLY, sendbuf);
  }
}

void setup()
{
  Serial.begin(115200); //初始化串口
  Wire.begin();
  sht20.begin();
  delay(3000);
  setupWifi();                                           //調用函數(shù)連接WIFI
  client.setServer(mqtt_server, port);                   //設置客戶端連接的服務器,連接Onenet服務器, 使用6002端口
  client.connect(mqtt_devid, mqtt_pubid, mqtt_password); //客戶端連接到指定的產品的指定設備.同時輸入鑒權信息
  if (client.connected())
  {
    Serial.println("OneNet is connected!"); //判斷以下是不是連好了.
  }
  client.subscribe(ONENET_TOPIC_PROP_SET);
  client.subscribe(ONENET_TOPIC_PROP_GET);
  client.setCallback(callback);
  tim1.attach(20, sendTempAndHumi); //定時每20秒調用一次發(fā)送數(shù)據(jù)函數(shù)sendTempAndHumi
}

void loop()
{
  temp = sht20.temperature();
  humi = sht20.humidity();
  if (!WiFi.isConnected()) //先看WIFI是否還在連接
  {
    setupWifi();
  }
  if (!client.connected()) //如果客戶端沒連接ONENET, 重新連接
  {
    clientReconnect();
    delay(100);
  }
  client.loop(); //客戶端循環(huán)檢測
}

四. 期望值獲取

#include <Arduino.h>
#include "WiFi.h"
#include "PubSubClient.h"
#include "Ticker.h"
#include "uFire_SHT20.h"
#include "ArduinoJson.h"

uFire_SHT20 sht20;

const char *ssid = "anlengkj";            //wifi名
const char *password = "al77776666";      //wifi密碼
const char *mqtt_server = "218.201.45.7"; //onenet 的 IP地址
const int port = 1883;                    //端口號

#define mqtt_pubid "Ygy2xf0iYx"    //產品ID
#define mqtt_devid "al00002lk0004" //設備名稱
//鑒權信息
#define mqtt_password "version=2018-10-31&res=products%2FYgy2xf0iYx%2Fdevices%2Fal00002lk0004&et=4083930061&method=md5&sign=LF58PMK3%2FRgB8n9CLVuhfA%3D%3D"

WiFiClient espClient;           //創(chuàng)建一個WIFI連接客戶端
PubSubClient client(espClient); // 創(chuàng)建一個PubSub客戶端, 傳入創(chuàng)建的WIFI客戶端
Ticker tim1;                    //定時器,用來循環(huán)上傳數(shù)據(jù)
float temp;
float humi;

//設備期望值獲取請求主題
#define ONENET_TOPIC_DESIRED_GET "$sys/" mqtt_pubid "/" mqtt_devid "/thing/property/desired/get"

//設備期望值獲取響應主題
#define ONENET_TOPIC_DESIRED_GET_RE "$sys/" mqtt_pubid "/" mqtt_devid "/thing/property/desired/get/reply"

//設備期望值刪除請求主題
#define ONENET_TOPIC_DESIRED_DEL "$sys/" mqtt_pubid "/" mqtt_devid "/thing/property/desired/delete"

//設備期望值刪除響應主題
#define ONENET_TOPIC_DESIRED_DEL_RE "$sys/" mqtt_pubid "/" mqtt_devid "/thing/property/desired/delete/reply"

//這是post上傳數(shù)據(jù)使用的模板
#define ONENET_POST_BODY_FORMAT "{\"id\":\"%u\",\"params\":%s}"
int postMsgId = 0; //記錄已經post了多少條

//連接WIFI相關函數(shù)
void setupWifi()
{
  delay(10);
  Serial.println("connect WIFI");
  WiFi.begin(ssid, password);
  while (!WiFi.isConnected())
  {
    Serial.print(".");
    delay(500);
  }
  Serial.println("OK");
  Serial.println("Wifi connected!");
}
void getDesired()
{
  if (client.connected())
  {
    //先拼接出json字符串
    char param[82];
    char jsonBuf[178];
    sprintf(param, "[\"set_flag\",\"temp_alarm\"]"); //我們把要上傳的數(shù)據(jù)寫在param里
    // sprintf(param, "[\"set_flag\",\"tempL\",\"tempLA\",\"tempU\",\"tempUA\"]"); //我們把要上傳的數(shù)據(jù)寫在param里
    postMsgId += 1;
    sprintf(jsonBuf, ONENET_POST_BODY_FORMAT, postMsgId, param);
    //再從mqtt客戶端中發(fā)布post消息
    if (client.publish(ONENET_TOPIC_DESIRED_GET, jsonBuf))
    {
      Serial.print("Post message to cloud: ");
      Serial.println(jsonBuf);
    }
    else
    {
      Serial.println("Publish message to cloud failed!");
    }
  }
}

//重連函數(shù), 如果客戶端斷線,可以通過此函數(shù)重連
void clientReconnect()
{
  while (!client.connected()) //再重連客戶端
  {
    Serial.println("reconnect MQTT...");
    if (client.connect(mqtt_devid, mqtt_pubid, mqtt_password))
    {
      Serial.println("connected");
    }
    else
    {
      Serial.println("failed");
      Serial.println(client.state());
      Serial.println("try again in 5 sec");
      delay(5000);
    }
  }
}

void callback(char *topic, byte *payload, unsigned int length)
{
  Serial.println("message rev:");
  Serial.println(topic);
  for (size_t i = 0; i < length; i++)
  {
    Serial.print((char)payload[i]);
  }
  Serial.println();
  if (strstr(topic, ONENET_TOPIC_DESIRED_GET))
  {
    DynamicJsonDocument doc(512);
    DeserializationError error = deserializeJson(doc, payload);
    if (error)
    {
      Serial.println("parse json failed");
      return;
    }
    JsonObject setAlinkMsgObj = doc.as<JsonObject>();
    serializeJsonPretty(setAlinkMsgObj, Serial);
    String str = setAlinkMsgObj["data"]["set_flag"]["value"];
    Serial.println(str);
  }
}

void setup()
{
  Serial.begin(115200); //初始化串口
  Wire.begin();
  sht20.begin();
  delay(3000);
  setupWifi();                                           //調用函數(shù)連接WIFI
  client.setServer(mqtt_server, port);                   //設置客戶端連接的服務器,連接Onenet服務器, 使用6002端口
  client.connect(mqtt_devid, mqtt_pubid, mqtt_password); //客戶端連接到指定的產品的指定設備.同時輸入鑒權信息
  if (client.connected())
  {
    Serial.println("OneNet is connected!"); //判斷以下是不是連好了.
  }
  client.subscribe(ONENET_TOPIC_DESIRED_GET);
  client.subscribe(ONENET_TOPIC_DESIRED_GET_RE);
  client.setCallback(callback);
  tim1.attach(20, getDesired); //定時每20秒調用一次發(fā)送數(shù)據(jù)函數(shù)sendTempAndHumi
}

void loop()
{
  temp = sht20.temperature();
  humi = sht20.humidity();
  if (!WiFi.isConnected()) //先看WIFI是否還在連接
  {
    setupWifi();
  }
  if (!client.connected()) //如果客戶端沒連接ONENET, 重新連接
  {
    clientReconnect();
    delay(100);
  }
  client.loop(); //客戶端循環(huán)檢測
}
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(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
  • 文/不壞的土叔 我叫張陵坑雅,是天一觀的道長辈挂。 經常有香客問我,道長裹粤,這世上最難降的妖魔是什么终蒂? 我笑而不...
    開封第一講書人閱讀 55,221評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上拇泣,老公的妹妹穿的比我還像新娘噪叙。我一直安慰自己,他們只是感情好霉翔,可當我...
    茶點故事閱讀 64,224評論 5 371
  • 文/花漫 我一把揭開白布睁蕾。 她就那樣靜靜地躺著,像睡著了一般早龟。 火紅的嫁衣襯著肌膚如雪惫霸。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,007評論 1 284
  • 那天葱弟,我揣著相機與錄音壹店,去河邊找鬼。 笑死芝加,一個胖子當著我的面吹牛硅卢,可吹牛的內容都是我干的。 我是一名探鬼主播藏杖,決...
    沈念sama閱讀 38,313評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼将塑,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了蝌麸?” 一聲冷哼從身側響起点寥,我...
    開封第一講書人閱讀 36,956評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎来吩,沒想到半個月后敢辩,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 43,441評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡弟疆,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 35,925評論 2 323
  • 正文 我和宋清朗相戀三年戚长,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片怠苔。...
    茶點故事閱讀 38,018評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡同廉,死狀恐怖,靈堂內的尸體忽然破棺而出柑司,到底是詐尸還是另有隱情迫肖,我是刑警寧澤,帶...
    沈念sama閱讀 33,685評論 4 322
  • 正文 年R本政府宣布攒驰,位于F島的核電站咒程,受9級特大地震影響,放射性物質發(fā)生泄漏讼育。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,234評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望奶段。 院中可真熱鬧饥瓷,春花似錦、人聲如沸痹籍。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽蹲缠。三九已至棺克,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間线定,已是汗流浹背娜谊。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評論 1 261
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留斤讥,地道東北人纱皆。 一個月前我還...
    沈念sama閱讀 45,467評論 2 352
  • 正文 我出身青樓,卻偏偏與公主長得像芭商,于是被迫代替她去往敵國和親派草。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,762評論 2 345

推薦閱讀更多精彩內容