doubao_chat/lib/net/turing/turing_iot.c

790 lines
21 KiB
C

#include "turing_iot.h"
#include "turing_mqtt.h"
#include "http/http_cli.h"
#include "json_c/json.h"
#include "json_c/json_tokener.h"
#include "os/os_api.h"
#include "server/ai_server.h"
struct turing_info {
httpcli_ctx ctx;
const char *api_key;
const char *device_id;
u8 auth_flag;
char client_id[65];
char topic[129];
char res_media_id[65];
int song_id;
char song_url[1024];
char song_title[256];
};
static OS_MUTEX iot_mutex;
static u8 turing_iot_close_flag = 1;
static int __http_post_mothed(const char *url, char *buffer, u32 length, int (*cb)(char *, void *), void *priv)
{
int error = 0;
http_body_obj http_body_buf;
struct turing_info *f = (struct turing_info *)priv;
httpcli_ctx *ctx = &f->ctx;
log_d("url->%s\n", url);
memset(&http_body_buf, 0x0, sizeof(http_body_obj));
http_body_buf.recv_len = 0;
http_body_buf.buf_len = 4 * 1024;
http_body_buf.buf_count = 1;
http_body_buf.p = (char *) malloc(http_body_buf.buf_len * sizeof(char));
if (http_body_buf.p == NULL) {
return -1;
}
os_mutex_pend(&iot_mutex, 0);
if (turing_iot_close_flag) {
free(http_body_buf.p);
os_mutex_post(&iot_mutex);
return -1;
}
memset(ctx, 0x0, sizeof(httpcli_ctx));
ctx->url = url;
ctx->priv = &http_body_buf;
ctx->post_data = buffer;
ctx->data_len = length;
ctx->data_format = "application/json";
ctx->connection = "close";
ctx->timeout_millsec = 6000;
error = httpcli_post(ctx);
os_mutex_post(&iot_mutex);
if (error == HERROR_OK) {
log_d("recv : %s\n", http_body_buf.p);
if (cb) {
error = cb(http_body_buf.p, priv);
}
} else {
error = -1;
}
if (http_body_buf.p) {
free(http_body_buf.p);
}
return error;
}
int turing_iot_set_key(void *priv, const char *api_key, const char *device_id)
{
struct turing_info *f = (struct turing_info *)priv;
f->api_key = api_key;
f->device_id = device_id;
f->auth_flag = 1;
return 0;
}
void *turing_iot_init(void)
{
struct turing_info *f = (struct turing_info *)calloc(sizeof(struct turing_info), 1);
if (!f) {
return NULL;
}
if (!os_mutex_valid(&iot_mutex)) {
os_mutex_create(&iot_mutex);
}
turing_iot_close_flag = 0;
return f;
}
int turing_iot_uninit(void *priv)
{
free(priv);
return 0;
}
int turing_iot_qiut_notify(void *priv)
{
int err;
struct turing_info *f = (struct turing_info *)priv;
turing_iot_close_flag = 1;
if (!f) {
return -1;
}
do {
http_cancel_dns(&f->ctx);
err = os_mutex_pend(&iot_mutex, 10);
if (!err) {
break;
}
} while (1);
os_mutex_post(&iot_mutex);
return 0;
}
__attribute__((weak)) const char *get_turing_version_code(void)
{
return "0.0.0";
}
//49965
#define AUSTR "{\"apiKey\":\"%s\",\"productId\":\"%d\",\"devices\":[{\"deviceId\":\"%s\",\"mac\":\"%s\"}]}"
int turing_iot_authorize(void *priv, int product_id, const char *mac)
{
int ret = 0;
struct turing_info *f = (struct turing_info *)priv;
char buffer[512];
int length = snprintf(buffer, sizeof(buffer), AUSTR, f->api_key, product_id, f->device_id, mac);
ret = __http_post_mothed(IOT_ADDR"/vendor/new/authorize", buffer, length, NULL, priv);
if (ret) {
log_e("%s http_post fail\n", __func__);
return -1;
}
return ret;
}
#define CHAUSTR "{\"apiKey\":\"%s\",\"deviceId\":\"%s\"}"
int turing_iot_check_authorize(void *priv)
{
int ret = 0;
struct turing_info *f = (struct turing_info *)priv;
char buffer[256];
int length = snprintf(buffer, sizeof(buffer), CHAUSTR, f->api_key, f->device_id);
ret = __http_post_mothed(IOT_ADDR"/vendor/new/device/status", buffer, length, NULL, priv);
if (ret) {
log_e("%s http_post fail\n", __func__);
return -1;
}
return ret;
}
/************************************************************/
/*获取微信accessToke*/
/************************************************************/
static int get_topic_callback(char *data, void *priv)
{
struct turing_info *f = (struct turing_info *)priv;
int err = -1;
json_object *new_obj = NULL;
json_object *data1 = NULL;
json_object *clientId = NULL;
json_object *topic = NULL;
new_obj = json_tokener_parse(data);
if (!json_object_object_get_ex(new_obj, "payload", &data1)) {
goto __result_exit;
}
if (!json_object_object_get_ex(data1, "clientId", &clientId)) {
goto __result_exit;
}
if (!json_object_get_string(clientId) || !json_object_get_string_len(clientId)) {
goto __result_exit;
}
if (!json_object_object_get_ex(data1, "topic", &topic)) {
goto __result_exit;
}
if (!json_object_get_string(topic) || !json_object_get_string_len(topic)) {
goto __result_exit;
}
strncpy(f->client_id, json_object_get_string(clientId), sizeof(f->client_id));
f->client_id[sizeof(f->client_id) - 1] = 0;
strncpy(f->topic, json_object_get_string(topic), sizeof(f->topic));
f->topic[sizeof(f->topic) - 1] = 0;
err = 0;
__result_exit:
json_object_put(new_obj);
return err;
}
#define GETOSTR "{\"apiKey\":\"%s\",\"deviceId\":\"%s\"}"
int turing_iot_get_topic(void *priv)
{
int ret = 0;
struct turing_info *f = (struct turing_info *)priv;
char buffer[256];
int length = snprintf(buffer, sizeof(buffer), GETOSTR, f->api_key, f->device_id);
ret = __http_post_mothed(IOT_ADDR"/iot/mqtt/topic", buffer, length, get_topic_callback, priv);
if (ret) {
log_e("%s http_post fail\n", __func__);
}
return ret;
}
#define NOSTSTR "{\"apiKey\":\"%s\",\"deviceId\":\"%s\",\"type\":%d,\"status\":{%s}}"
int turing_iot_notify_status(void *priv, u8 type, const char *status_buffer)
{
int ret = 0;
struct turing_info *f = (struct turing_info *)priv;
char *buffer = malloc(1024);
if (!buffer) {
return -1;
}
int length = snprintf(buffer, 1024, NOSTSTR, f->api_key, f->device_id, type, status_buffer);
ret = __http_post_mothed(IOT_ADDR"/iot/status/notify", buffer, length, NULL, priv);
if (ret) {
log_e("%s http_post fail\n", __func__);
}
free(buffer);
return ret;
}
/************************************************************/
#define BOUNDARY "--jieli&boundary&e3#due*hf$n"
static const char http_head_tab[] =
"POST /resources/file/upload?apiKey=%s HTTP/1.1\r\n"
"Host: iot-ai.tuling123.com\r\n"
"User-Agent: */*\r\n"
"Cache-Control: no-cache\r\n"
"Connection: close\r\n"
"Content-type: multipart/form-data; boundary="BOUNDARY"\r\n"
"Content-Length: %d\r\n"
"\r\n";
static const char http_data_f[] =
"--"BOUNDARY"\r\n"
"Content-Disposition: form-data; name=\"speech\"; filename=\"%s\"\r\n"
"Content-Type: %s\r\n"
"\r\n";
static const char http_data_b[] =
"\r\n--"BOUNDARY"--\r\n";
static int __post_resources(const char *url, u8 *buffer, u32 length, int (*cb)(char *, void *), void *priv)
{
int error = 0;
int url_buf_len = 2048;
char *url_buf = NULL;
http_body_obj http_body_buf;
struct turing_info *f = (struct turing_info *)priv;
httpcli_ctx *ctx = &f->ctx;
char *http_body_before_buf = NULL;
int http_body_before_len = 0;
memset(&http_body_buf, 0x0, sizeof(http_body_obj));
url_buf = calloc(1, url_buf_len + sizeof(http_data_f) + 64);
if (!url_buf) {
goto __checkin_exit;
}
http_body_before_buf = url_buf + url_buf_len;
http_body_buf.recv_len = 0;
http_body_buf.buf_len = 1024;
http_body_buf.buf_count = 1;
http_body_buf.p = (char *) malloc(http_body_buf.buf_len * sizeof(char));
if (http_body_buf.p == NULL) {
goto __checkin_exit;
}
http_body_before_len = snprintf(http_body_before_buf, sizeof(http_data_f) + 64, http_data_f, "voice.amr", "application/octet-stream");
if (http_body_before_len >= sizeof(http_data_f) + 64) {
goto __checkin_exit;
}
int http_more_data_addr[3];
int http_more_data_len[3 + 1];
http_more_data_addr[0] = (int)(http_body_before_buf);
http_more_data_addr[1] = (int)(buffer);
http_more_data_addr[2] = (int)(http_data_b);
http_more_data_len[0] = http_body_before_len;
http_more_data_len[1] = length;
http_more_data_len[2] = strlen(http_data_b);
http_more_data_len[3] = 0;
memset(ctx, 0x0, sizeof(httpcli_ctx));
ctx->more_data = http_more_data_addr;
ctx->more_data_len = http_more_data_len;
ctx->timeout_millsec = 8000;
ctx->url = url;
ctx->priv = &http_body_buf;
snprintf(url_buf, url_buf_len, http_head_tab, f->api_key, (int)(http_body_before_len + length + strlen(http_data_b)));
ctx->user_http_header = url_buf;
error = httpcli_post(ctx);
if (error == HERROR_OK) {
if (cb) {
error = cb(http_body_buf.p, priv);
}
} else {
error = -1;
}
__checkin_exit:
if (url_buf) {
free(url_buf);
}
if (http_body_buf.p) {
free(http_body_buf.p);
}
return error;
}
static int post_res_callback(char *data, void *priv)
{
struct turing_info *f = (struct turing_info *)priv;
int err = -1;
json_object *new_obj = NULL;
json_object *data1 = NULL;
new_obj = json_tokener_parse(data);
if (!json_object_object_get_ex(new_obj, "payload", &data1)) {
goto __result_exit;
}
if (!json_object_get_string(data1) || !json_object_get_string_len(data1)) {
goto __result_exit;
}
strncpy(f->res_media_id, json_object_get_string(data1), sizeof(f->res_media_id));
f->res_media_id[sizeof(f->res_media_id) - 1] = 0;
log_d("f->res_media_id=%s\n", f->res_media_id);
err = 0;
__result_exit:
json_object_put(new_obj);
return err;
}
/*不使用 toUser参数*/
#define MESSSTR "{\"apiKey\":\"%s\",\"deviceId\":\"%s\",\"type\":%d,\"message\":{\"mediaId\":\"%s\"}}"
int turing_iot_send_message(void *priv, u8 type)
{
int ret = 0;
struct turing_info *f = (struct turing_info *)priv;
char buffer[512];
int length = snprintf(buffer, sizeof(buffer), MESSSTR, f->api_key, f->device_id, type, f->res_media_id);
ret = __http_post_mothed(IOT_ADDR"/iot/message/send", buffer, length, NULL, priv);
if (ret) {
log_e("%s http_post fail\n", __func__);
return -1;
}
return ret;
}
int turing_iot_post_res(u8 *buf, u32 len)
{
int ret = 0;
char buffer[256];
struct turing_info *f = get_turing_iot_hdl();
if (!f || turing_iot_close_flag || !f->auth_flag) {
return -1;
}
os_mutex_pend(&iot_mutex, 0); //find xueyong
if (turing_iot_close_flag) {
os_mutex_post(&iot_mutex);
return -1;
}
int length = snprintf(buffer, sizeof(buffer), IOT_ADDR"/resources/file/upload?apiKey=%s", f->api_key);
ret = __post_resources(buffer, buf, len, post_res_callback, f);
if (ret) {
log_e("%s http_post res fail\n", __func__);
goto exit;
}
length = snprintf(buffer, sizeof(buffer), MESSSTR, f->api_key, f->device_id, 0, f->res_media_id);
ret = __http_post_mothed(IOT_ADDR"/iot/message/send", buffer, length, NULL, f);
if (ret) {
log_e("%s http_post send message fail\n", __func__);
}
exit:
os_mutex_post(&iot_mutex);
return ret;
}
/************************************************************/
static int get_music_res_callback(char *data, void *priv)
{
struct turing_info *f = (struct turing_info *)priv;
int err = -1;
json_object *new_obj = NULL;
json_object *data1 = NULL;
json_object *url = NULL;
json_object *title = NULL;
json_object *id = NULL;
json_object *tip = NULL;
char buf[128];
new_obj = json_tokener_parse(data);
if (!json_object_object_get_ex(new_obj, "payload", &data1)) {
goto __result_exit;
}
if (!json_object_object_get_ex(data1, "url", &url)) {
goto __result_exit;
}
if (!json_object_get_string(url) || !json_object_get_string_len(url)) {
goto __result_exit;
}
if (!json_object_object_get_ex(data1, "name", &title)) {
goto __result_exit;
}
if (!json_object_get_string(title) || !json_object_get_string_len(title)) {
goto __result_exit;
}
if (!json_object_object_get_ex(data1, "id", &id)) {
goto __result_exit;
}
strncpy(f->song_url, json_object_get_string(url), sizeof(f->song_url));
f->song_url[sizeof(f->song_url) - 1] = 0;
strncpy(f->song_title, json_object_get_string(title), sizeof(f->song_title));
f->song_title[sizeof(f->song_title) - 1] = 0;
f->song_id = json_object_get_int(id);
snprintf(buf, sizeof(buf), "\"title\":\"%s\",\"mediaId\":%d,\"play\":1", json_object_get_string(title), json_object_get_int(id));
if (0 == turing_iot_notify_status(f, MUSIC_STATE, buf)) {
err = 0;
}
__result_exit:
json_object_put(new_obj);
return err;
}
/*不使用 toUser参数*/
#define AURESTR "{\"apiKey\":\"%s\",\"deviceId\":\"%s\",\"type\":%d}"
int turing_iot_get_music_res(void *priv, u8 type)
{
int ret = 0;
struct turing_info *f = (struct turing_info *)priv;
char buffer[256];
int length = snprintf(buffer, sizeof(buffer), AURESTR, f->api_key, f->device_id, type);
ret = __http_post_mothed(IOT_ADDR"/v2/iot/audio", buffer, length, get_music_res_callback, priv);
if (ret) {
log_e("%s http_post fail\n", __func__);
}
return ret;
}
#define COLLECT "{\"apiKey\":\"%s\",\"deviceId\":\"%s\",\"id\":%d}"
#define PLAY_COLLECT "{\"apiKey\":\"%s\",\"deviceId\":\"%s\",\"type\":0}"
int turing_iot_collect_resource(void *priv, int album_id, u8 is_play)
{
int length = 0;
int ret = 0;
struct turing_info *f = (struct turing_info *)priv;
char buffer[256];
if (is_play) {
length = snprintf(buffer, sizeof(buffer), PLAY_COLLECT, f->api_key, f->device_id);
ret = __http_post_mothed(IOT_ADDR"/v2/iot/collect", buffer, length, get_music_res_callback, priv);
} else {
length = snprintf(buffer, sizeof(buffer), COLLECT, f->api_key, f->device_id, album_id);
ret = __http_post_mothed(IOT_ADDR"/v2/iot/audio/collect", buffer, length, NULL, priv);
}
if (ret) {
log_e("%s http_post fail\n", __func__);
}
return ret;
}
#define INITVER "{\"apiKey\":\"%s\",\"deviceId\":\"%s\",\"currentVersion\":\"%s\"}"
int turing_iot_report_version(void *priv)
{
int ret = 0;
struct turing_info *f = (struct turing_info *)priv;
char buffer[256];
int length = snprintf(buffer, sizeof(buffer), INITVER, f->api_key, f->device_id, get_turing_version_code());
ret = __http_post_mothed(IOT_ADDR"/iot/v2/ota/initVersion", buffer, length, NULL, priv);
if (ret) {
log_e("%s http_post fail\n", __func__);
}
return ret;
}
#define UPDATESUCC "{\"apiKey\":\"%s\",\"deviceId\":\"%s\",\"id\":%d,\"updateStatus\":1}"
static int turing_iot_update_success(void *priv, int version_id)
{
int ret = 0;
struct turing_info *f = (struct turing_info *)priv;
char buffer[256];
int length = snprintf(buffer, sizeof(buffer), UPDATESUCC, f->api_key, f->device_id, version_id);
ret = __http_post_mothed(IOT_ADDR"/iot/v2/ota/updateStatus", buffer, length, NULL, priv);
if (ret) {
log_e("%s http_post fail\n", __func__);
}
return ret;
}
static int ota_update_version_info(void *priv, const char *buf)
{
json_object *new_obj = NULL;
json_object *payload = NULL;
json_object *data = NULL;
json_object *data2 = NULL;
int id = 0;
int ret = -1;
new_obj = json_tokener_parse(buf);
if (!new_obj) {
return -1;
}
if (!json_object_object_get_ex(new_obj, "payload", &payload)) {
goto __result_exit;
}
if (!json_object_object_get_ex(payload, "updateStatus", &data)) {
goto __result_exit;
}
if (0 != json_object_get_int(data)) {
goto __result_exit;
}
if (!json_object_object_get_ex(payload, "agree", &data)) {
goto __result_exit;
}
if (1 != json_object_get_int(data)) {
goto __result_exit;
}
if (!json_object_object_get_ex(payload, "id", &data)) {
goto __result_exit;
}
id = json_object_get_int(data);
if (0 == id) {
goto __result_exit;
}
if (!json_object_object_get_ex(payload, "nextVersion", &data2)) {
goto __result_exit;
}
if (NULL == json_object_get_string(data2) || 0 == json_object_get_string_len(data2)) {
goto __result_exit;
}
if (!json_object_object_get_ex(payload, "currentVersion", &data)) {
goto __result_exit;
}
if (NULL == json_object_get_string(data) || 0 == json_object_get_string_len(data)) {
goto __result_exit;
}
if (strcmp(json_object_get_string(data), get_turing_version_code())) {
goto __result_exit;
}
if (!strcmp(json_object_get_string(data2), json_object_get_string(data))) {
goto __result_exit;
}
if (!json_object_object_get_ex(payload, "firmwareUrl", &data)) {
goto __result_exit;
}
if (NULL == json_object_get_string(data) || 0 == json_object_get_string_len(data)) {
goto __result_exit;
}
extern void turing_upgrade_notify(int event, void *arg);
turing_upgrade_notify(AI_SERVER_EVENT_UPGRADE, NULL);
extern int get_update_data(const char *url);
ret = get_update_data(json_object_get_string(data));
if (!ret) {
ret = turing_iot_update_success(priv, id);
char *msg = NULL;
msg = (char *)malloc(json_object_get_string_len(data2) + 1);
if (msg) {
strcpy(msg, json_object_get_string(data2));
}
turing_upgrade_notify(AI_SERVER_EVENT_UPGRADE_SUCC, msg);
} else {
turing_upgrade_notify(AI_SERVER_EVENT_UPGRADE_FAIL, NULL);
}
__result_exit:
if (new_obj) {
json_object_put(new_obj);
}
return ret;
}
int turing_iot_check_update(void *priv)
{
int error = 0;
http_body_obj http_body_buf;
struct turing_info *f = (struct turing_info *)priv;
httpcli_ctx *ctx = &f->ctx;
char url[128];
memset(&http_body_buf, 0x0, sizeof(http_body_obj));
http_body_buf.recv_len = 0;
http_body_buf.buf_len = 4 * 1024;
http_body_buf.buf_count = 1;
http_body_buf.p = (char *) malloc(http_body_buf.buf_len * sizeof(char));
if (http_body_buf.p == NULL) {
return -1;
}
os_mutex_pend(&iot_mutex, 0);
if (turing_iot_close_flag) {
free(http_body_buf.p);
os_mutex_post(&iot_mutex);
return -1;
}
snprintf(url, sizeof(url), "http://iot-ai.tuling123.com/iot/v2/ota/version?apiKey=%s&deviceId=%s", f->api_key, f->device_id);
memset(ctx, 0x0, sizeof(httpcli_ctx));
ctx->url = url;
ctx->priv = &http_body_buf;
ctx->connection = "close";
error = httpcli_get(ctx);
os_mutex_post(&iot_mutex);
if (error == HERROR_OK) {
log_d("ota recv : %s\n", http_body_buf.p);
error = ota_update_version_info(priv, http_body_buf.p);
}
if (http_body_buf.p) {
free(http_body_buf.p);
}
return error;
}
#define BT_CFG_BIND "[{\"apiKey\":\"%s\",\"deviceId\":\"%s\",\"openId\":\"%s\"}]"
int turing_iot_bt_cfg_bind(void *priv, const char *openid)
{
int ret = 0;
struct turing_info *f = (struct turing_info *)priv;
char buffer[256];
int length = snprintf(buffer, sizeof(buffer), BT_CFG_BIND, f->api_key, f->device_id, openid);
ret = __http_post_mothed(IOT_ADDR"/open/device/bind-wechat-user", buffer, length, NULL, priv);
if (ret) {
log_e("%s http_post fail\n", __func__);
}
return ret;
}
#define SINVOICE_CFG_BIND "{\"apiKey\":\"%s\",\"deviceId\":\"%s\",\"openId\":\"%s\"}"
int turing_iot_sinvoice_cfg_bind(void *priv, const char *openid)
{
int ret = 0;
struct turing_info *f = (struct turing_info *)priv;
char buffer[256];
int length = snprintf(buffer, sizeof(buffer), SINVOICE_CFG_BIND, f->api_key, f->device_id, openid);
ret = __http_post_mothed(IOT_ADDR"/iot/bind_from_sinvoice", buffer, length, NULL, priv);
if (ret) {
log_e("%s http_post fail\n", __func__);
}
return ret;
}
/************************************************************/
char *turing_iot_get_client_id(void *priv)
{
struct turing_info *f = (struct turing_info *)priv;
return f->client_id;
}
char *turing_iot_get_topic_uuid(void *priv)
{
struct turing_info *f = (struct turing_info *)priv;
return f->topic;
}
char *turing_iot_get_url(void *priv)
{
struct turing_info *f = (struct turing_info *)priv;
return f->song_url;
}
int turing_iot_get_song_title(void *priv, char *title, int *id)
{
struct turing_info *f = (struct turing_info *)priv;
strcpy(title, f->song_title);
*id = f->song_id;
return 0;
}