• [其他] 分享从数据到文本的自然语言生成:准备 Transformer
    从数据到文本的自然语言生成:准备 Transformer随着知识图谱(更广义地说是结构化数据)在 2020 年被广泛应用于 NLP 领域,我们可以看到大量利用一系列 RDF 三元组/AMR 图/一系列表单元的自然语言生成(NLG)方法,它们可以生成说明或问题等连贯的人类可读的文本。此外,当前的各种 RDF-to-text 方法仅仅在 WebNLG 2017 上进行了评价,然而新一轮的条挑战——WebNLG 2020(https://webnlg-challenge.loria.fr/challenge_2020/)已经到来,如果你是一名自然语言生成研究人员,请参与到这项新的挑战中。下面这条 Dmitry Lepikhin 的推特很好地概括了今年 NLG 领域的发展趋势。我们需要设计复杂的规划器和执行器吗?需要使用结构化的对齐技术吗?实际上,使用优秀的预训练语言模型就可以得到不错的效果。事实上,加入预训练的语言模型并将一些示例输入给它确实是有效的。Chen 等人在论文「Few-Shot NLG with Pre-Trained Language Model」(https://www.aclweb.org/anthology/2020.acl-main.18.pdf)中,使用一些表中的信息以及 GPT-2 解码器说明了这一现象。他们首次将表单元输入给了一个可学习的 LSTM 编码器,从而得到拷贝机制的隐藏状态。另一方面,输入 GPT-2 的文本使用了冻结的权重。这种拷贝机制有助于保留表单元中的稀有词例。作者在 WikiBio 上进行的实验表明,仅仅使用 200 个训练示例就足以生成比复杂的强对比基线更好的文本。同样是使用表数据,Chen 等人在论文「Logical Natural Language Generation from Open-Domain Tables」(https://www.aclweb.org/anthology/2020.acl-main.708.pdf)中构建了一个新的数据集 LogicNLG,它需要在标准的文本生成方法的基础上使用额外的逻辑。例如,我们需要使用一些比较和计数操作来纳入「1 more gold medal」或「most gold medals」等部分,这些部分会使得生成的文本更加自然和生动。用于实验数据集的对比基线使用了预训练的 GPT-2 和 BERT,但似乎在这个任务上的语言模型仍然还有很大的提升空间。Song 等人在论文「Structural Information Preserving for Graph-to-Text Generation」(https://www.aclweb.org/anthology/2020.acl-main.712.pdf)中,应用了一个稍加修改的 Transformer 编码器,它显式地处理了表面形式的关系。模型的输入就是一个线性化的图(你可以通过深度优先搜索 DFS 等方式构建)。解码器并没有对 Transformer 做任何修改。该方法关键的部分在于向标准的语言模型损失中添加了两种自编码损失,它们是专门为了捕获与语言化图的结构而设计的。第一个损失重建了三元关系,另一个损失则重建了线性化输入图的节点和连边的标签。在 AMR 和 RDF 图(WebNLG)上进行的实验说明,仅仅加入这两种损失就可以在 BLEU 指标上提升 2 个点。在这里,我想劝大家:每个人都应该停止使用 BLEU 评价 NLG 的质量(https://www.aclweb.org/anthology/2020.acl-main.448.pdf)。ACL 2020 的最佳论文提名奖获得者也是这么认为的。WebNLG 2020 的组织者也非常赞同这一观点,他们在经典的度量标准之外,正式地加入了 chrF++ 和 BertScore 两种度量标准。此外,在 ACL 2020 上,研究人员提出了一种新的度量标准 BLEURT(https://www.aclweb.org/anthology/2020.acl-main.704.pdf),它与人类的判断更相符。尽管如此,Zhao 等人在论文「Bridging the Structural Gap Between Encoding and Decoding for Data-To-Text Generation」(https://www.aclweb.org/anthology/2020.acl-main.224.pdf)中提出了一种「编码器-规划器-解码器」模型 DualEnc。首先,他们对输入图进行预处理,从而将某种关系变换为一个显式的节点。这样一来,该节点就会包含一些有标签的边「s->p, p->s, p->o, o->p」。接着,他们通过 R-GCN 对该图进行编码,从而得到实体和关系的嵌入。他们还是用另一个考虑了额外的特征的 R-GCN 对同一个图进行编码,从而说明某种关系是否已经被利用了。他们通过以下的方式构建内容规划:当存在未访问的关系时,softmax 选择最可能的关系,然后将该关系添加到内容规划中。一旦序列准备好了,它就被扩展为这些关系的主语和宾语。最后,通过 LSTM 对生成的序列进行编码。他们将图编码和规划编码输入解码器,从而生成输出结果。转自,MrBear,https://www.leiphone.com/category/academic/n3WcOtLYehqcrpXv.html
  • [其他] 分享NLP自然语言生成的评价与假设
    再次思考自然语言生成的评价与假设作为对话系统的从业者,在我看来,自然语言生成任务的复杂性是很棘手的。尤其是,对于研究社区来说,对模型的评价仍然是一个非常富有正义的问题,因此看到研究者们积极地改善现状是十分令人鼓舞的。对于初学者来说,Maxime Peyrard(https://www.aclweb.org/anthology/P19-1502)证明了,在评价特定得分范围内的性能时,某些用于文本自动摘要的自动化的评价指标存在不一致性。Clark 等人(https://homes.cs.washington.edu/~nasmith/papers/clark+celikyilmaz+smith.acl19.pdf)也提出了一种新的基于句子移动相似度(sentence mover’s similarity)的生成文本评价指标,该指标被证明比标准的 ROUGE 指标更符合人类的判断。模型生成的文本往往会出现「事实错误」(factual errors)和「虚假陈述」(spurious statements)的问题。因此,Falke 等人(https://leoribeiro.github.io/papers/acl19-summary-correctness.pdf)研究了是否可以用自然语言推理系统对输出进行重排序,从而解决该问题。他们发现现成的自然语言推理系统并不能适用于下游任务,并提供了一些使这些系统能够达到必要性能的工具。Maxime Peyrard 的更加基础的工作(https://www.aclweb.org/anthology/P19-1101)则在理论上严格地定义了本文自动摘要领域的某些概念(例如,冗余度、相关性、信息量)。除了模型评价,Sankar 等人(https://arxiv.org/abs/1906.01603)的优秀工作对「传统的基于循环神经网络」和「基于 Transformer」的序列到序列(Seq2Seq)的对话模型从对话历史中学到的某些假设提出了质疑。他们特别指出,这些模型对于某些应用于上下文的扰动并不十分敏感,这对目前的自然语言对话生成器提出了挑战。转自,MrBear,https://www.leiphone.com/category/academic/6e0VKaqUCAEhjj0q.html
  • [技术干货] 华为云IoT设备接入密码C语言生成
    华为云IoT设备接入密码C语言生成Andy 2021-3-18一、问题去年给客户(华为SaaS生态链企业,名字匿了)定制了一款高性价比DTU网关,支持协议定制、远程配置、断缓续传。有些朋友想拿样品测试,问题来了:网关接入华为IoT云的参数(ClientId、Username、Password等)一般是从客户的应用后台获取,如果没有后台或者后台对接比较麻烦怎么办?先看看这些参数是怎么来的:https://support.huaweicloud.com/api-iothub/iot_06_v5_3009.html1. ClientId(1) 设备ID① 产品ID② 设备标识码(2) 时间戳2. Username设备ID3. Password由HMACSHA256算法生成(1) 加密密钥:时间戳(2) 明文:设备密钥。以上各个参数中,只有设备标志码每个设备不同,其他均为固定值,即设备与云平台保持一致即可,核心是实现HMACSHA256算法(正好在宇宙四大行做加密谋生-_-||),以下简要分述。 二、云平台客户用自己的华为云账号按以下参数创建产品、注册设备后,不必配置任何参数,网关即可自动上云。三、工具生成https://iot-tool.obs-website.cn-north-4.myhuaweicloud.com/四、算法检验http://www.jsons.cn/allencrypt/五、代码生成X86平台有openSSL,JAVA有Cipher包,瘦弱的MCU只能直接用源代码了,感谢这位大兄弟(不知是不是扒的openSSL源码?):https://blog.csdn.net/miniphoenix/article/details/110135164代码扒下来精简了下,输出由hex改为string,OK~// HMAC_SHA256.c #include "HMAC_SHA256.h" #include "stdint.h" #include <stdio.h>  #include <stdlib.h> #include <string.h> //------------------------------------------------------------------------------ #define SHA256_BLOCKLEN  64ul //size of message block buffer #define SHA256_DIGESTLEN 32ul //size of digest in uint8_t #define SHA256_DIGESTINT 8ul  //size of digest in uint32_t   //------------------------------------------------------------------------------ typedef struct sha256_ctx_t {   uint64_t len;                 // processed message length   uint32_t h[SHA256_DIGESTINT]; // hash state   uint8_t buf[SHA256_BLOCKLEN]; // message block buffer } SHA256_CTX;   void sha256_init(SHA256_CTX *ctx); void sha256_update(SHA256_CTX *ctx, const uint8_t *m, uint32_t mlen); // resets state: calls sha256_init void sha256_final(SHA256_CTX *ctx, uint8_t *md);   //------------------------------------------------------------------------------ typedef struct hmac_sha256_ctx_t {   uint8_t buf[SHA256_BLOCKLEN]; // key block buffer, not needed after init   uint32_t h_inner[SHA256_DIGESTINT];   uint32_t h_outer[SHA256_DIGESTINT];   SHA256_CTX sha; } HMAC_SHA256_CTX;   void hmac_sha256_init(HMAC_SHA256_CTX *hmac, const uint8_t *key, uint32_t keylen); void hmac_sha256_update(HMAC_SHA256_CTX *hmac, const uint8_t *m, uint32_t mlen); // resets state to hmac_sha256_init void hmac_sha256_final(HMAC_SHA256_CTX *hmac, uint8_t *md);   //------------------------------------------------------------------------------ void pbkdf2_sha256(HMAC_SHA256_CTX *ctx,     const uint8_t *key, uint32_t keylen, const uint8_t *salt, uint32_t saltlen, uint32_t rounds,     uint8_t *dk, uint32_t dklen);   //------------------------------------------------------------------------------   #include <string.h>   //#define ROR(n,k) ((n >> k) | (n << (32 - k)))   static uint32_t ror(uint32_t n, uint32_t k) {   return (n >> k) | (n << (32 - k)); }   #define ROR(n,k) ror(n,k)   #define CH(x,y,z)  (z ^ (x & (y ^ z))) #define MAJ(x,y,z) ((x & y) | (z & (x | y))) #define S0(x)      (ROR(x, 2) ^ ROR(x,13) ^ ROR(x,22)) #define S1(x)      (ROR(x, 6) ^ ROR(x,11) ^ ROR(x,25)) #define R0(x)      (ROR(x, 7) ^ ROR(x,18) ^ (x>>3)) #define R1(x)      (ROR(x,17) ^ ROR(x,19) ^ (x>>10))   static const uint32_t K[64] = {   0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,   0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,   0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,   0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,   0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,   0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,   0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,   0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 };   static void sha256_transform(SHA256_CTX *s, const uint8_t *buf) {   uint32_t t1, t2, a, b, c, d, e, f, g, h, m[64];   uint32_t i, j;      for (i = 0, j = 0; i < 16; i++, j += 4)   {     m[i] = (uint32_t) buf[j] << 24 | (uint32_t) buf[j + 1] << 16 |            (uint32_t) buf[j + 2] << 8 | (uint32_t) buf[j + 3];   }   for (; i < 64; i++)   {     m[i] = R1(m[i - 2]) + m[i - 7] + R0(m[i - 15]) + m[i - 16];   }   a = s->h[0];   b = s->h[1];   c = s->h[2];   d = s->h[3];   e = s->h[4];   f = s->h[5];   g = s->h[6];   h = s->h[7];   for (i = 0; i < 64; i++)   {     t1 = h + S1(e) + CH(e, f, g) + K[i] + m[i];     t2 = S0(a) + MAJ(a, b, c);     h = g;     g = f;     f = e;     e = d + t1;     d = c;     c = b;     b = a;     a = t1 + t2;   }   s->h[0] += a;   s->h[1] += b;   s->h[2] += c;   s->h[3] += d;   s->h[4] += e;   s->h[5] += f;   s->h[6] += g;   s->h[7] += h; }   void sha256_init(SHA256_CTX *s) {   s->len = 0;      s->h[0] = 0x6a09e667;   s->h[1] = 0xbb67ae85;   s->h[2] = 0x3c6ef372;   s->h[3] = 0xa54ff53a;   s->h[4] = 0x510e527f;   s->h[5] = 0x9b05688c;   s->h[6] = 0x1f83d9ab;   s->h[7] = 0x5be0cd19; }   void sha256_final(SHA256_CTX *s, uint8_t *md) {   uint32_t r = s->len % SHA256_BLOCKLEN;   int i;      //pad   s->buf[r++] = 0x80;   if (r > 56)   {     memset(s->buf + r, 0, SHA256_BLOCKLEN - r);     r = 0;     sha256_transform(s, s->buf);   }   memset(s->buf + r, 0, 56 - r);   s->len *= 8;   s->buf[56] = s->len >> 56;   s->buf[57] = s->len >> 48;   s->buf[58] = s->len >> 40;   s->buf[59] = s->len >> 32;   s->buf[60] = s->len >> 24;   s->buf[61] = s->len >> 16;   s->buf[62] = s->len >> 8;   s->buf[63] = s->len;   sha256_transform(s, s->buf);      for (i = 0; i < SHA256_DIGESTINT; i++)   {     md[4 * i    ] = s->h[i] >> 24;     md[4 * i + 1] = s->h[i] >> 16;     md[4 * i + 2] = s->h[i] >> 8;     md[4 * i + 3] = s->h[i];   }   sha256_init(s); }   void sha256_update(SHA256_CTX *s, const uint8_t *m, uint32_t len) {   const uint8_t *p = m;   uint32_t r = s->len % SHA256_BLOCKLEN;      s->len += len;   if (r)   {     if (len + r < SHA256_BLOCKLEN)     {       memcpy(s->buf + r, p, len);       return;     }     memcpy(s->buf + r, p, SHA256_BLOCKLEN - r);     len -= SHA256_BLOCKLEN - r;     p += SHA256_BLOCKLEN - r;     sha256_transform(s, s->buf);   }   for (; len >= SHA256_BLOCKLEN; len -= SHA256_BLOCKLEN, p += SHA256_BLOCKLEN)   {     sha256_transform(s, p);   }   memcpy(s->buf, p, len); }   #define INNER_PAD '\x36' #define OUTER_PAD '\x5c'   void hmac_sha256_init(HMAC_SHA256_CTX *hmac, const uint8_t *key, uint32_t keylen) {   SHA256_CTX *sha = &hmac->sha;   uint32_t i;      if (keylen <= SHA256_BLOCKLEN)   {     memcpy(hmac->buf, key, keylen);     memset(hmac->buf + keylen, '\0', SHA256_BLOCKLEN - keylen);   }   else   {     sha256_init(sha);     sha256_update(sha, key, keylen);     sha256_final(sha, hmac->buf);     memset(hmac->buf + SHA256_DIGESTLEN, '\0', SHA256_BLOCKLEN - SHA256_DIGESTLEN);   }      for (i = 0; i < SHA256_BLOCKLEN; i++)   {     hmac->buf[ i ] = hmac->buf[ i ] ^ OUTER_PAD;   }      sha256_init(sha);   sha256_update(sha, hmac->buf, SHA256_BLOCKLEN);   // copy outer state   memcpy(hmac->h_outer, sha->h, SHA256_DIGESTLEN);      for (i = 0; i < SHA256_BLOCKLEN; i++)   {     hmac->buf[ i ] = (hmac->buf[ i ] ^ OUTER_PAD) ^ INNER_PAD;   }      sha256_init(sha);   sha256_update(sha, hmac->buf, SHA256_BLOCKLEN);   // copy inner state   memcpy(hmac->h_inner, sha->h, SHA256_DIGESTLEN); }   void hmac_sha256_update(HMAC_SHA256_CTX *hmac, const uint8_t *m, uint32_t mlen) {   sha256_update(&hmac->sha, m, mlen); }   void hmac_sha256_final(HMAC_SHA256_CTX *hmac, uint8_t *md) {   SHA256_CTX *sha = &hmac->sha;   sha256_final(sha, md);      // reset sha to outer state   memcpy(sha->h, hmac->h_outer, SHA256_DIGESTLEN);   sha->len = SHA256_BLOCKLEN;      sha256_update(sha, md, SHA256_DIGESTLEN);   sha256_final(sha, md); // md = D(outer || D(inner || msg))      // reset sha to inner state -> reset hmac   memcpy(sha->h, hmac->h_inner, SHA256_DIGESTLEN);   sha->len = SHA256_BLOCKLEN; }   void pbkdf2_sha256(HMAC_SHA256_CTX *hmac,     const uint8_t *key, uint32_t keylen, const uint8_t *salt, uint32_t saltlen, uint32_t rounds,     uint8_t *dk, uint32_t dklen) {   uint8_t *U;   uint8_t *T;   uint8_t count[4];   uint32_t i, j, k;   uint32_t len;     uint32_t hlen = SHA256_DIGESTLEN;   uint32_t l = dklen / hlen + ((dklen % hlen) ? 1 : 0);   uint32_t r = dklen - (l - 1) * hlen;      hmac_sha256_init(hmac, key, keylen);      U = hmac->buf;   T = dk;      len = hlen;   for (i = 1; i <= l; i++)   {     if (i == l) { len = r; }     count[0] = (i >> 24) & 0xFF;     count[1] = (i >> 16) & 0xFF;     count[2] = (i >>  8) & 0xFF;     count[3] = (i) & 0xFF;     hmac_sha256_update(hmac, salt, saltlen);     hmac_sha256_update(hmac, count, 4);     hmac_sha256_final(hmac, U);     memcpy(T, U, len);     for (j = 1; j < rounds; j++)     {       hmac_sha256_update(hmac, U, hlen);       hmac_sha256_final(hmac, U);       for (k = 0; k < len; k++)       {         T[k] ^= U[k];       }     }     T += len;   }    } void compute_sha_ex(unsigned char* dest, const uint8_t *msg, uint32_t mlen) {   uint8_t md[SHA256_DIGESTLEN] = {0};   SHA256_CTX sha;   sha256_init(&sha);   sha256_update(&sha, msg, mlen);   sha256_final(&sha, md);   memcpy(dest, md, SHA256_DIGESTLEN); }   void compute_hmac_ex(unsigned char* dest, const uint8_t *key, uint32_t klen, const uint8_t *msg, uint32_t mlen) {   uint8_t md[SHA256_DIGESTLEN] = {0};   HMAC_SHA256_CTX hmac;   hmac_sha256_init  (&hmac, key, klen);   hmac_sha256_update(&hmac, msg, mlen);   hmac_sha256_final (&hmac, md); #if 0   // hex value   memcpy(dest, md, SHA256_DIGESTLEN); #else   // string of hex value   for (int i = 0; i < SHA256_DIGESTLEN; i++)   {     sprintf(dest, "%s%02x", dest, md[i]);   } #endif }// HMAC_SHA256.h #ifndef _HMAC_SHA256_H #define _HMAC_SHA256_H #ifndef uint8_t   typedef unsigned char   uint8_t; #endif #ifndef uint32_t   typedef unsigned int    uint32_t; #endif void compute_hmac_ex(unsigned char* dest, const uint8_t *key, uint32_t klen, const uint8_t *msg, uint32_t mlen); #endif// HuaweiIotToken.c // Andy 18676383370, 435223420@qq.com // https://support.huaweicloud.com/api-iothub/iot_06_v5_3009.html #include "HuaweiIotToken.h"   #include "HMAC_SHA256.h"   #include <stdio.h>  #include <string.h> #define TIME_STAMP_LEN            (10) int TOKEN_GetDeviceId(const uchar *productId, const uchar *deviceCode, uchar *deviceId) {   if ( !productId )   {     printf("[%s] input error: productId is NULL", __FUNCTION__);     return -10;   }   if ( !strlen(productId) )   {     printf("[%s] input error: productId is empty", __FUNCTION__);     return -11;   }   if ( !deviceCode )   {     printf("[%s] input error: deviceCode is NULL", __FUNCTION__);     return -20;   }   if ( !strlen(deviceCode) )   {     printf("[%s] input error: deviceCode is empty", __FUNCTION__);     return -21;   }   if ( !deviceId )   {     printf("[%s] input error: deviceId is NULL", __FUNCTION__);     return -30;   }      sprintf(deviceId, "%s_%s", productId, deviceCode);   return 0; } int TOKEN_GetClientId(const uchar *deviceId, const uchar *timeStamp, uchar *clientId) {   const uchar DEVICE_ID_TYPE[1+1]   = "0";   const uchar CIPHER_SIGN_TYPE[1+1] = "0";   if ( !deviceId )   {     printf("[%s] input error: productId is NULL", __FUNCTION__);     return -10;   }   if ( !strlen(deviceId) )   {     printf("[%s] input error: productId is empty", __FUNCTION__);     return -11;   }   if ( !timeStamp )   {     printf("[%s] input error: timeStamp is NULL", __FUNCTION__);     return -20;   }   if ( strlen(timeStamp) != TIME_STAMP_LEN )   {     printf("[%s] input error: timeStamp len %d", __FUNCTION__, strlen(timeStamp));     return -21;   }   if ( !clientId )   {     printf("[%s] input error: deviceCode is NULL", __FUNCTION__);     return -30;   }   sprintf(clientId, "%s_%s_%s_%s",                     deviceId,                     DEVICE_ID_TYPE,                     CIPHER_SIGN_TYPE,                     timeStamp);   return 0; } int TOKEN_GetPassword(const uchar *timeStamp, const uchar *deviceSecret, uchar *password) {   if ( !timeStamp )   {     printf("[%s] input error: timeStamp is NULL", __FUNCTION__);     return -10;   }   if ( strlen(timeStamp) != TIME_STAMP_LEN )   {     printf("[%s] input error: timeStamp len %d", __FUNCTION__, strlen(timeStamp));     return -11;   }   if ( !deviceSecret )   {     printf("[%s] input error: deviceSecret is NULL", __FUNCTION__);     return -20;   }   if ( !strlen(deviceSecret) )   {     printf("[%s] input error: deviceSecret is empty", __FUNCTION__);     return -21;   }   if ( !password )   {     printf("[%s] input error: password is NULL", __FUNCTION__);     return -30;   }   compute_hmac_ex(  password,                     timeStamp,                     strlen(timeStamp),                     deviceSecret,                     strlen(deviceSecret)  );      return 0; }// HuaweiIotToken.h #ifndef _HUAWEI_IOT_TOKEN_H #define _HUAWEI_IOT_TOKEN_H #ifndef uchar   typedef unsigned char   uchar; #endif int TOKEN_GetDeviceId(const uchar *productId, const uchar *deviceCode,   uchar *deviceId); int TOKEN_GetClientId(const uchar *deviceId,  const uchar *timeStamp,    uchar *clientId); int TOKEN_GetPassword(const uchar *timeStamp, const uchar *deviceSecret, uchar *password); #endif// test.c #include "HuaweiIotToken.h" #include <stdio.h> #define MAX_STR_LEN               (256) #define CLIENT_ID_LEN             (256) #define USERNAME_LEN              (256) #define PASSWORD_LEN              (256) #define PRODUCT_ID                "myProductId" #define IMEI                      "864424044187240" #define DEVICE_SECRET             "12345678" #define DEVICE_REG_TIME_STAMP     "2021031803" int main(int argc,char **argv)   {   int ret = 0;   uchar deviceId[MAX_STR_LEN + 1]   = {0};   ret = TOKEN_GetDeviceId(PRODUCT_ID, IMEI, deviceId);   if ( ret ) return -1;   printf("product id  : %s\n", PRODUCT_ID);   printf("device code : %s\n", IMEI);   printf("device id   : %s\n", deviceId);   printf("\n");   uchar clientId[CLIENT_ID_LEN + 1] = {0};   ret = TOKEN_GetClientId(deviceId, DEVICE_REG_TIME_STAMP, clientId);   if ( ret ) return -2;   printf("device id   : %s\n", deviceId);   printf("time stamp  : %s\n", DEVICE_REG_TIME_STAMP);   printf("client id   : %s\n", clientId);   printf("\n");   uchar password[PASSWORD_LEN + 1] = {0};   ret = TOKEN_GetPassword(DEVICE_REG_TIME_STAMP, DEVICE_SECRET, password);   if ( ret ) return -3;   printf("timeStamp   : %s\n", DEVICE_REG_TIME_STAMP);   printf("deviceSecret: %s\n", DEVICE_SECRET);   printf("password    : %s\n", password);   printf("\n");   return 0; }编译,运行。。。生成的password完全一致,欧耶~d52820682c39ed6875c351ddcc1329580de6edd6c9056e6b8190342222f62af1
总条数:33 到第
上滑加载中