日韩美女乱婬AAA高清视频_国产色爱AV资源综合区_国产女同性黄网在线观看_欧美日韩一卡2卡3卡4卡新区乱码_俺来也俺也啪www色_精品久久久久久综合日本_99国内偷揿国产精品人妻_国产蜜芽剧果冻传媒_日本特级aaaaaaaa片_国产偷人妻精品一区二区在线

簡(jiǎn)體中文

基于AVAPIs的事件回放

回放功能對(duì)接指南 | TUTK P2P SDK 開(kāi)發(fā)手冊(cè)
回放功能對(duì)接流程圖

圖 1:回放功能對(duì)接流程圖

一、回放功能對(duì)接指南

(一)概覽
本章節(jié)主要討論影像類(lèi)產(chǎn)品的標(biāo)準(zhǔn)功能——回放功能的對(duì)接引導(dǎo),閱覽本章節(jié)的前提是,開(kāi)發(fā)者已經(jīng)可以使用AVAPIs進(jìn)行實(shí)時(shí)觀看。
主要涉及到的模塊是:IOTCAPIs、AVAPIs。
主要涉及到的API是:avSendIOCtrl/avRecvIOCtrl、avClientStartEx/avServStartEx、avRecvFrameData2/avSendFrameData、avClientStop/avServStop
(二)核心要點(diǎn)
  1. 1、回放的前提,是要先建立P2P連線和AV通道。
  2. 2、如果是使用AVAPIs做下載功能,一定要開(kāi)啟resend功能。開(kāi)啟的方法就是將avClientStartExavServStartEx參數(shù)里面的resend設(shè)置為1。
  3. 3、建議設(shè)備端要檢查avSendFrameData的返回值,如果返回值是-20006(緩存區(qū)溢出),需要進(jìn)行重傳此幀;特別是下載功能。
  4. 4、回放結(jié)束兩端的處理建議:
    • (1)設(shè)備端:
      • 送完最后一幀后,需要使用avResendBufUsageRate檢查緩存區(qū)是否還有數(shù)據(jù)沒(méi)送出,只有緩存區(qū)清空的情況下,才代表數(shù)據(jù)已經(jīng)完全送出,才能關(guān)閉通道。
      • 最后一幀,需要把frameInfo里面的tag標(biāo)記為1。非最后一幀為0。
      • 緩存區(qū)清空后,建議延時(shí)1s再關(guān)閉通道,以免APP端還沒(méi)收完數(shù)據(jù)。
    • (2)APP端:
      • APP需要判斷frameInfo的tag是否為1,為1時(shí)表示已收完最后一幀,可以進(jìn)行關(guān)閉和釋放資源的操作。
  5. 5、文件下載:文件下載的流程與上述流程基本一樣,唯一的差異是,不像回放的送流方式,在下載的時(shí)候,設(shè)備端可以不按照一幀一幀的方式送,可以每次送固定大小字節(jié)數(shù)的二進(jìn)制流給APP端,APP端只做保存即可。具體流程可以參考:基于AVAPIs的文件下載。
(三)代碼示例
1. APP端實(shí)現(xiàn)
1.1 查詢(xún)事件列表
APP端向設(shè)備發(fā)送事件列表查詢(xún)請(qǐng)求,指定查詢(xún)時(shí)間范圍和事件類(lèi)型,通過(guò)avSendIOCtrl接口發(fā)送。
/** * 發(fā)送事件列表查詢(xún)請(qǐng)求 * @brief 向設(shè)備查詢(xún)指定時(shí)間范圍內(nèi)的所有事件記錄 * @param avIndex AV通道索引(已建立P2P連接的通道) * @return 0=發(fā)送成功,<0=發(fā)送失?。ㄥe(cuò)誤碼參考SDK文檔) */ int queryEventList(int avIndex) {    SMsgAVIoctrlListEventReq req = {0};        // 設(shè)置查詢(xún)起始時(shí)間(1970-01-01 00:00:00)    req.stStartTime.year   = 1970;   // 年份    req.stStartTime.month  = 1;      // 月份(1-12)    req.stStartTime.day    = 1;      // 日期(1-31)    req.stStartTime.wday   = 1;      // 星期(0=周日,1=周一...6=周六)    req.stStartTime.hour   = 0;      // 小時(shí)(0-23)    req.stStartTime.minute = 0;      // 分鐘(0-59)    req.stStartTime.second = 0;      // 秒(0-59)        // 設(shè)置查詢(xún)結(jié)束時(shí)間(1970-01-02 00:00:00)    req.stEndTime.year   = 1970;    req.stEndTime.month  = 1;    req.stEndTime.day    = 2;    req.stEndTime.wday   = 1;    req.stEndTime.hour   = 0;    req.stEndTime.minute = 0;    req.stEndTime.second = 0;        req.event = AVIOCTRL_EVENT_ALL;   // 查詢(xún)所有類(lèi)型事件        int ret = 0;    // 發(fā)送IO控制指令    if((ret = avSendIOCtrl(avIndex, IOTYPE_USER_IPCAM_LISTEVENT_REQ, &req, sizeof(req))) < 0){        printf("send IO Ctrl failed, error=%d\n", ret);    } else {        printf("查詢(xún)事件列表請(qǐng)求發(fā)送成功\n");    }    return ret; }
說(shuō)明:avIndex 為已建立P2P連接的AV通道索引,需確保P2P連接正常后再調(diào)用該接口;時(shí)間參數(shù)需嚴(yán)格按照結(jié)構(gòu)體定義格式填充,避免參數(shù)錯(cuò)誤導(dǎo)致查詢(xún)失敗。
1.2 通知設(shè)備啟動(dòng)回放
APP端向設(shè)備發(fā)送回放啟動(dòng)指令,指定回放起始時(shí)間,通過(guò)IOTYPE_USER_IPCAM_RECORD_PLAYCONTROL命令碼標(biāo)識(shí)操作類(lèi)型。
/** * 發(fā)送回放啟動(dòng)指令 * @brief 通知設(shè)備啟動(dòng)指定時(shí)間點(diǎn)的回放功能 * @param avIndex AV通道索引 * @param startTime 回放起始時(shí)間結(jié)構(gòu)體 * @return 0=發(fā)送成功,<0=發(fā)送失敗 */ int startPlayback(int avIndex, const STime *startTime) {    if (startTime == NULL) {        printf("無(wú)效參數(shù):起始時(shí)間為空\(chéng)n");        return -1;    }        SMsgAVIoctrlPlayRecord req = {0};    // 復(fù)制起始時(shí)間    req.stStartTime = *startTime;    req.command = AVIOCTRL_RECORD_PLAY_START;   // 回放啟動(dòng)命令        int ret = 0;    if((ret = avSendIOCtrl(avIndex, IOTYPE_USER_IPCAM_RECORD_PLAYCONTROL, &req, sizeof(req))) < 0){        printf("send IO Ctrl failed, error=%d\n", ret);    } else {        printf("回放啟動(dòng)指令發(fā)送成功\n");    }    return ret; }
1.3 接收設(shè)備回放響應(yīng)
APP端通過(guò)avRecvIOCtrl接收設(shè)備的回放響應(yīng),若響應(yīng)為回放啟動(dòng)成功,則創(chuàng)建回放線程處理后續(xù)音視頻數(shù)據(jù)接收。
/** * 監(jiān)聽(tīng)設(shè)備回放響應(yīng) * @brief 循環(huán)接收設(shè)備的IO控制響應(yīng),處理回放啟動(dòng)結(jié)果 * @param avIndex AV通道索引 * @return 0=正常退出,<0=異常退出 */ int listenPlaybackResp(int avIndex) {    int ret = 0;    int cmd = 0;    char buf[1024] = {0};   // 接收緩沖區(qū)        while (1) {        // 接收IO控制響應(yīng)(超時(shí)時(shí)間100ms)        ret = avRecvIOCtrl(avIndex, &cmd, buf, 1024, 100);        if(ret < 0){            if(ret != AV_ER_TIMEOUT){                printf("avRecvIOCtrl error:%d\n", ret);                break;            }            continue;   // 超時(shí)繼續(xù)等待        }                // 處理回放控制響應(yīng)        if(IOTYPE_USER_IPCAM_RECORD_PLAYCONTROL_RESP == cmd){            SMsgAVIoctrlPlayRecordResp *resp = (SMsgAVIoctrlPlayRecordResp*)buf;            if(resp->command == AVIOCTRL_RECORD_PLAY_START){                if(resp->result > 0){                    printf("回放啟動(dòng)成功,通道ID:%d\n", resp->result);                    // 創(chuàng)建回放線程,處理音視頻數(shù)據(jù)接收                    pthread_t playbackThread;                    if (pthread_create(&playbackThread, NULL, (void*)playbackWorker, (void*)&avIndex) != 0) {                        printf("創(chuàng)建回放線程失敗\n");                    } else {                        pthread_detach(playbackThread);   // 分離線程,自動(dòng)回收資源                    }                } else {                    printf("回放啟動(dòng)失敗,錯(cuò)誤碼:%d\n", resp->result);                }                break;   // 處理完成退出循環(huán)            }        }    }    return ret; }
1.4 回放線程(視頻接收)
回放線程通過(guò)avClientStartEx創(chuàng)建AV通道(開(kāi)啟resend=1),循環(huán)調(diào)用avRecvFrameData2接收視頻幀,判斷frameInfo.tag是否為1(最后一幀),是則退出線程并關(guān)閉通道。
// 全局線程控制標(biāo)志(0=運(yùn)行,1=停止) volatile int g_playback_stop = 0; /** * 回放線程函數(shù) * @brief 創(chuàng)建AV客戶(hù)端通道,接收視頻幀數(shù)據(jù)并處理 * @param arg 傳入?yún)?shù)(AV通道索引) * @return NULL */ void* playbackWorker(void* arg) {    int avIndex = *(int*)arg;    AVClientStartInConfig in;    AVClientStartOutConfig out;    FRAMEINFO frameInfo = {0};   // 幀信息結(jié)構(gòu)體    int ret = 0;    int playback_index = -1;        // 初始化配置結(jié)構(gòu)體    memset(&in, 0, sizeof(in));    memset(&out, 0, sizeof(out));        in.cb = sizeof(in);    in.iotc_session_id = sid;   // 會(huì)話ID(從P2P連接中獲?。?    in.iotc_channel_id = playback_channel;   // 回放通道ID    in.timeout_sec = 10;   // 超時(shí)時(shí)間(秒)    in.account_or_identity = "admin";   // 設(shè)備賬號(hào)    in.password_or_token = "888888";   // 設(shè)備密碼    in.resend = 1;   // 開(kāi)啟resend功能,確保下載數(shù)據(jù)完整性    in.security_mode = AV_SECURITY_AUTO;   // 自動(dòng)安全模式    in.auth_type = AV_AUTH_PASSWORD;   // 密碼認(rèn)證方式    in.sync_recv_data = 0;   // 異步接收數(shù)據(jù)        out.cb = sizeof(out);    // 創(chuàng)建AV客戶(hù)端通道    playback_index = avClientStartEx(&in, &out);    printf("avClientStartEx return %d\n", playback_index);    if(playback_index < 0){        printf("創(chuàng)建回放通道失敗\n");        return NULL;    }        // 創(chuàng)建音頻接收線程    pthread_t audioThread;    if (pthread_create(&audioThread, NULL, (void*)audioRecvWorker, (void*)&playback_index) != 0) {        printf("創(chuàng)建音頻接收線程失敗\n");    } else {        pthread_detach(audioThread);    }        // 接收視頻幀數(shù)據(jù)    unsigned char frame_buf[40960] = {0};   // 視頻幀緩沖區(qū)(40KB)    while(!g_playback_stop){        // 接收視頻幀(超時(shí)時(shí)間默認(rèn))        ret = avRecvFrameData2(playback_index, frame_buf, sizeof(frame_buf), NULL, NULL, (char*)&frameInfo, sizeof(FRAMEINFO), NULL, NULL);        if(ret < 0){            if(ret == AV_ERR_DATA_NOREADY){                msleep(5);   // 無(wú)數(shù)據(jù)時(shí)短暫休眠                continue;            }            printf("接收視頻幀失敗,錯(cuò)誤碼:%d\n", ret);            break;        }        else if(ret > 0){            // 解碼播放處理(開(kāi)發(fā)者需實(shí)現(xiàn)解碼邏輯)            // decodeAndRender(frame_buf, ret, &frameInfo);                        // 判斷是否為最后一幀            if(frameInfo.tag == 1){                printf("收到最后一幀,準(zhǔn)備退出回放\n");                g_playback_stop = 1;                break;            }        }    }        // 等待音頻線程退出    msleep(100);    // 關(guān)閉AV通道,釋放資源    avClientStop(playback_index);    printf("回放線程退出\n");    return NULL; }
說(shuō)明:resend參數(shù)必須設(shè)置為1,否則下載功能可能出現(xiàn)數(shù)據(jù)丟失;視頻幀緩沖區(qū)大小需根據(jù)實(shí)際碼率調(diào)整(建議不小于40KB),避免緩沖區(qū)溢出;解碼播放邏輯需根據(jù)設(shè)備端編碼格式(如H.264/H.265)實(shí)現(xiàn)。
1.5 音頻接收線程
獨(dú)立音頻線程通過(guò)avRecvAudioData接收音頻數(shù)據(jù),解碼播放后檢查是否為最后一幀,確保音視頻同步退出。
/** * 音頻接收線程函數(shù) * @brief 接收音頻幀數(shù)據(jù)并處理 * @param arg 傳入?yún)?shù)(回放通道索引) * @return NULL */ void* audioRecvWorker(void* arg) {    int playback_index = *(int*)arg;    FRAMEINFO frameInfo = {0};    int ret = 0;    unsigned char audio_buf[10240] = {0};   // 音頻緩沖區(qū)(10KB)        while(!g_playback_stop){        // 接收音頻幀數(shù)據(jù)        ret = avRecvAudioData(playback_index, audio_buf, sizeof(audio_buf), NULL, NULL, &frameInfo, sizeof(FRAMEINFO), NULL);        if(ret < 0){            if(ret == AV_ERR_DATA_NOREADY){                msleep(5);                continue;            }            printf("接收音頻幀失敗,錯(cuò)誤碼:%d\n", ret);            break;        }        else if(ret > 0){            // 音頻解碼播放處理(開(kāi)發(fā)者需實(shí)現(xiàn)解碼邏輯)            // audioDecodeAndPlay(audio_buf, ret, &frameInfo);                        // 判斷是否為最后一幀            if(frameInfo.tag == 1){                g_playback_stop = 1;                break;            }        }    }        printf("音頻接收線程退出\n");    return NULL; }
2. 設(shè)備端實(shí)現(xiàn)
2.1 接收并處理回放指令
設(shè)備端接收APP的回放啟動(dòng)指令,分配通道ID后通過(guò)avSendIOCtrl返回響應(yīng),通道分配成功則創(chuàng)建回放線程發(fā)送音視頻數(shù)據(jù)。
/** * 處理APP端回放控制指令 * @brief 接收APP的回放啟動(dòng)/停止指令,分配通道并返回響應(yīng) * @param avIndex AV通道索引 * @return 0=正常處理,<0=處理失敗 */ int handlePlaybackCtrl(int avIndex) {    int ret = 0;    int cmd = 0;    char buf[1024] = {0};   // 接收緩沖區(qū)    int sid = 0;   // 會(huì)話ID(從P2P連接中獲?。?        while (1) {        // 接收IO控制指令(超時(shí)時(shí)間100ms)        ret = avRecvIOCtrl(avIndex, &cmd, buf, 1024, 100);        if(ret < 0){            if(ret != AV_ER_TIMEOUT){                printf("avRecvIOCtrl error:%d\n", ret);                break;            }            continue;        }                // 處理回放控制指令        if(IOTYPE_USER_IPCAM_RECORD_PLAYCONTROL == cmd){            SMsgAVIoctrlPlayRecordResp resp = {0};            SMsgAVIoctrlPlayRecord *req = (SMsgAVIoctrlPlayRecord*)buf;                        // 檢查是否為回放啟動(dòng)命令            if(req->command == AVIOCTRL_RECORD_PLAY_START){                // 分配回放通道ID(自定義實(shí)現(xiàn))                int channel = get_available_channel(sid);                resp.command = AVIOCTRL_RECORD_PLAY_START;   // 響應(yīng)命令碼                                if(channel > 0){                    resp.result = channel;   // 返回分配的通道ID                    printf("回放通道分配成功,通道ID:%d\n", channel);                                        // 發(fā)送響應(yīng)                    if((ret = avSendIOCtrl(avIndex, IOTYPE_USER_IPCAM_RECORD_PLAYCONTROL_RESP, &resp, sizeof(resp))) >= 0){                        // 創(chuàng)建回放線程,發(fā)送音視頻數(shù)據(jù)                        pthread_t playbackThread;                        PlaybackParam param = {sid, channel, req->stStartTime};                        if (pthread_create(&playbackThread, NULL, (void*)devicePlaybackWorker, (void*)&param) != 0) {                            printf("創(chuàng)建回放線程失敗\n");                        } else {                            pthread_detach(playbackThread);                        }                    }                }                else{                    resp.result = -3;   // 通道分配失敗                    printf("回放通道分配失敗\n");                    // 發(fā)送失敗響應(yīng)                    avSendIOCtrl(avIndex, IOTYPE_USER_IPCAM_RECORD_PLAYCONTROL_RESP, &resp, sizeof(resp));                }                break;            }        }    }    return ret; } // 回放參數(shù)結(jié)構(gòu)體 typedef struct {    int sid;               // 會(huì)話ID    int channel;           // 通道ID    STime startTime;       // 回放起始時(shí)間 } PlaybackParam;
說(shuō)明:get_available_channel 為通道獲取接口(示例可參考:IOTC空閑通道的獲取),需確保返回的通道ID唯一且未被占用;線程創(chuàng)建后建議設(shè)置為分離模式,避免資源泄漏;響應(yīng)命令碼需與請(qǐng)求命令碼一致,確保APP端正確識(shí)別。
2.2 設(shè)備端回放線程(數(shù)據(jù)發(fā)送)
設(shè)備端回放線程通過(guò)avServStartEx創(chuàng)建AV服務(wù)端通道(開(kāi)啟resend),讀取本地音視頻文件后通過(guò)avSendFrameData/avSendAudioData發(fā)送數(shù)據(jù);遇到緩存區(qū)溢出時(shí)重傳數(shù)據(jù);發(fā)送完成后檢查緩存區(qū)并延時(shí)1s關(guān)閉通道。
// 宏定義配置 #define ENABLE_RESEND 1   // 開(kāi)啟resend功能 #define ENABLE_DTLS 0   // 關(guān)閉DTLS加密 #define MAX_FRAME_SIZE 40960 // 最大幀大?。?0KB) // 外部函數(shù)聲明 void readFrameFromLocalFile(const STime *startTime, FrameData *frame); // 從本地文件讀取幀數(shù)據(jù) int get_available_channel(int sid); // 獲取可用通道ID int ExPasswordAuthCallBackFn(void* param); // 密碼認(rèn)證回調(diào)函數(shù) // 幀數(shù)據(jù)結(jié)構(gòu)體定義 typedef struct {    bool isVideo;          // 是否視頻幀    bool isAudio;          // 是否音頻幀    unsigned char* data; // 幀數(shù)據(jù)指針    int dataLen;           // 數(shù)據(jù)長(zhǎng)度 } FrameData; /** * 設(shè)備端回放線程函數(shù) * @brief 創(chuàng)建AV服務(wù)端通道,讀取本地音視頻文件并發(fā)送給APP端 * @param arg 傳入?yún)?shù)(PlaybackParam結(jié)構(gòu)體指針) * @return NULL */ void* devicePlaybackWorker(void* arg) {    PlaybackParam *param = (PlaybackParam*)arg;    int ret = -1;    AVServStartInConfig avStartInConfig;    AVServStartOutConfig avStartOutConfig;    FRAMEINFO frameInfo = {0};   // 幀信息結(jié)構(gòu)體    unsigned char buffer[MAX_FRAME_SIZE] = {0}; // 數(shù)據(jù)緩沖區(qū)    bool isLastFrame = false; // 是否最后一幀標(biāo)志    FrameData frame = {0};    frame.data = buffer; // 綁定緩沖區(qū)        // 初始化AV服務(wù)端配置    memset(&avStartInConfig, 0, sizeof(avStartInConfig));    avStartInConfig.cb                  = sizeof(AVServStartInConfig);    avStartInConfig.iotc_session_id     = param->sid; // 會(huì)話ID    avStartInConfig.iotc_channel_id     = param->channel; // 通道ID(與響應(yīng)中一致)    avStartInConfig.timeout_sec         = 30; // 超時(shí)時(shí)間(秒)    avStartInConfig.password_auth       = &ExPasswordAuthCallBackFn; // 密碼認(rèn)證回調(diào)    avStartInConfig.server_type         = SERVTYPE_STREAM_SERVER; // 流服務(wù)器類(lèi)型    avStartInConfig.resend              = ENABLE_RESEND; // 開(kāi)啟resend功能        // 安全模式配置 #if ENABLE_DTLS    avStartInConfig.security_mode = AV_SECURITY_DTLS; // 啟用DTLS加密 #else    avStartInConfig.security_mode = AV_SECURITY_SIMPLE; // 簡(jiǎn)單安全模式 #endif    avStartOutConfig.cb                  = sizeof(AVServStartOutConfig);        // 創(chuàng)建AV服務(wù)端通道    int playback_index = avServStartEx(&avStartInConfig, &avStartOutConfig);    if(playback_index < 0){        printf("創(chuàng)建回放服務(wù)端通道失敗,錯(cuò)誤碼:%d\n", playback_index);        return NULL;    }    printf("回放服務(wù)端通道創(chuàng)建成功,索引:%d\n", playback_index);        // 循環(huán)發(fā)送音視頻數(shù)據(jù)    while(!isLastFrame){        // 從本地文件讀取音視頻幀(需開(kāi)發(fā)者實(shí)現(xiàn)具體邏輯)        readFrameFromLocalFile(&param->startTime, &frame);                // 解復(fù)用圖像和聲音(需開(kāi)發(fā)者實(shí)現(xiàn))        // demuxFrame(&frame);                // 初始化幀信息        memset(&frameInfo, 0, sizeof(frameInfo));        if(isLastFrame){            frameInfo.tag = 1; // 最后一幀標(biāo)記        }                // 發(fā)送幀數(shù)據(jù)        if(frame.isVideo && frame.data != NULL && frame.dataLen > 0){            // 發(fā)送視頻幀:遇-20006(緩存區(qū)溢出)則重傳            do{                ret = avSendFrameData(playback_index, frame.data, frame.dataLen, (const void*)&frameInfo, sizeof(FRAMEINFO));                if(ret == -20006){ // 緩存區(qū)溢出,等待后重傳                    msleep(20);                }            } while(ret == -20006);        }        else if(frame.isAudio && frame.data != NULL && frame.dataLen > 0){            // 發(fā)送音頻幀:遇-20006(緩存區(qū)溢出)則重傳            do{                ret = avSendAudioData(playback_index, frame.data, frame.dataLen, (const void*)&frameInfo, sizeof(FRAMEINFO));                if(ret == -20006){                    msleep(20);                }            } while(ret == -20006);        }                // 處理發(fā)送結(jié)果        if(ret < 0 && ret != -20006){            printf("發(fā)送幀數(shù)據(jù)失敗,錯(cuò)誤碼:%d\n", ret);            break;        }                // 檢查是否為最后一幀(需根據(jù)實(shí)際文件讀取邏輯判斷)        // isLastFrame = checkIsLastFrame();    }        // 檢查緩存區(qū)是否清空(確保所有數(shù)據(jù)已發(fā)送)    int i_count = 0;    while(i_count++ < 10*300){ // 最多等待30秒        float userate = avResendBufUsageRate(playback_index);        if(userate > 0.0){            msleep(100);        } else {            break;        }    }        // 延時(shí)1s后關(guān)閉通道,確保APP端收完數(shù)據(jù)    msleep(1000);    avServStop(playback_index);    printf("回放服務(wù)端通道關(guān)閉,線程退出\n");        return NULL; }

特別注意

1. 生產(chǎn)環(huán)境中,readFrameFromLocalFiledemuxFrame 需根據(jù)實(shí)際的文件存儲(chǔ)格式(如MP4/TS)和編碼格式(H.264/H.265/AAC)實(shí)現(xiàn),確保幀數(shù)據(jù)正確讀取和解復(fù)用;

2. 緩存區(qū)溢出重傳機(jī)制必須實(shí)現(xiàn)(錯(cuò)誤碼-20006),否則可能導(dǎo)致數(shù)據(jù)丟失;

3. 最后一幀的tag標(biāo)記需嚴(yán)格設(shè)置為1,且必須等待重傳緩沖區(qū)清空后再關(guān)閉通道,避免APP端遺漏數(shù)據(jù)。

即刻開(kāi)啟您的物聯(lián)網(wǎng)之旅

聯(lián)系解決方案專(zhuān)家
Kalay App
資訊安全白皮書(shū)
全球?qū)@季?/a>
解決方案
新聞動(dòng)態(tài)
公司動(dòng)態(tài)
行業(yè)資訊
媒體報(bào)道
永續(xù)發(fā)展
經(jīng)營(yíng)者的話
社會(huì)參與
環(huán)境永續(xù)
公司治理

+86 755 27702549

7×24小時(shí)服務(wù)熱線

法律聲明 隱私權(quán)條款

關(guān)注“TUTK”

TUTK服務(wù)盡在掌握

? 2022 物聯(lián)智慧科技(深圳)有限公司版權(quán)所有粵ICP備14023641號(hào)
在線咨詢(xún)
掃一掃

TUTK服務(wù)盡在掌握

全國(guó)免費(fèi)服務(wù)熱線
+86 755 27702549

返回頂部