#include <WiFi.h>
#include "HMAC_SHA256.h"
#include <ArduinoJson.h>
#include <ArduinoWebsockets.h>
const char *ssid = "Wokwi-GUEST"; //你的网络名称
const char *password = ""; //你的网络密码
String appid = "1f087f98"; //填写控制台中获取的 APPID 信息
String api_secret = "OTI3MmY3NjYzODYzNTIwNTI5ZmNiMTMz"; //填写控制台中获取的 APISecret 信息
String api_key = "4d0b0a4d7c3d97d5bda6819af45722c4"; //填写控制台中获取的 APIKey 信息
String Spark_url = "ws://spark-api.xf-yun.com/v2.1/chat";
String domain = "your_domain"; // Replace with your actual domain
String question = "Hello, ChatGPT!"; // Replace with your actual question
const char *ntpServer = "pool.ntp.org";
const long gmtOffset_sec = 8 * 3600;
const int daylightOffset_sec = 0;
// String getHostFromURL(const String &url) {
// int hostStart = url.indexOf("://") + 3;
// int hostEnd = url.indexOf("/", hostStart);
// return url.substring(hostStart, hostEnd);
// }
// String getPathFromURL(const String &url) {
// int pathStart = url.indexOf("/", url.indexOf("://") + 3);
// int pathEnd = url.indexOf("?", pathStart);
// if (pathEnd == -1) {
// pathEnd = url.length(); // If no query params, use the end of the string
// }
// return url.substring(pathStart, pathEnd);
// }
class Ws_Param {
private:
String APPID;
String APIKey;
String APISecret;
String host;
String path;
String Spark_url;
public:
Ws_Param(String _APPID, String _APIKey, String _APISecret, String _Spark_url) {
APPID = _APPID;
APIKey = _APIKey;
APISecret = _APISecret;
Spark_url = _Spark_url;
host = getHostFromURL(_Spark_url);
path = getPathFromURL(_Spark_url);
}
String create_url() {
// Generate RFC1123 formatted timestamp
// struct timeval tv;
// gettimeofday(&tv, NULL);
// time_t now = tv.tv_sec;
// struct tm timeinfo;
// gmtime_r(&now, &timeinfo);
// char date[50];
// strftime(date, sizeof(date), "%a, %d %b %Y %H:%M:%S GMT", &timeinfo);
struct tm timeinfo;
if (!getLocalTime(&timeinfo))
{
Serial.println("fail to obtain time");
}
char date[50]; // Buffer to hold the formatted time
// Format the time as RFC1123
strftime(date, sizeof(date), "%a, %d %b %Y %H:%M:%S GMT", &timeinfo);
// Construct signature origin string
String signature_origin = "host: " + host + "\n";
signature_origin += "date: " + String(date) + "\n";
signature_origin += "GET " + path + " HTTP/1.1";
Serial.print("signature_origin:");
Serial.println(signature_origin);
String signature_sha_base64 = SHA256_output(APIKey.c_str(), signature_origin.c_str());
Serial.print("signature_sha_base64:");
Serial.println(signature_sha_base64);
// Construct authorization header
String authorization_origin = "api_key=\"" + APIKey + "\", algorithm=\"hmac-sha256\", headers=\"host date request-line\", signature=\"" + signature_sha_base64 + "\"";
Serial.print("authorization_origin:");
Serial.println(authorization_origin);
//base64_encode(authorization_base64, (char *)authorization_origin.c_str(), authorization_origin.length());
unsigned char authorization[213];
size_t outlen = 0;
mbedtls_base64_encode(NULL, 0, &outlen, (unsigned char *)authorization_origin.c_str(), strlen(authorization_origin.c_str()));
Serial.print("outlen: ");
Serial.println(outlen);
mbedtls_base64_encode(authorization, outlen, &outlen, (unsigned char *)authorization_origin.c_str(), strlen(authorization_origin.c_str()));
// null-terminate the output string
authorization[outlen] = 0;
//String authorization_base64 = (const char*)authorization;
String authorization_base64 = (const char*)authorization;
Serial.print("authorization_base64: ");
Serial.println(authorization_base64);
// Serial.print("authorization_base64:");
// Serial.println(authorization_base64);
// Construct the request parameters dictionary
//String v = "authorization=" + String(authorization_base64) + "&date=" + String(date) + "&host=" + host;
// Construct the final URL
String url = Spark_url + "?" + "authorization=" + String(authorization_base64) + "&date=" + urlencode(String(date)) + "&host=" + host;
return url;
}
private:
String getHostFromURL(const String &url) {
int hostStart = url.indexOf("://") + 3;
int hostEnd = url.indexOf("/", hostStart);
return url.substring(hostStart, hostEnd);
}
String getPathFromURL(const String &url) {
int pathStart = url.indexOf("/", url.indexOf("://") + 3);
int pathEnd = url.indexOf("?", pathStart);
if (pathEnd == -1) {
pathEnd = url.length(); // If no query params, use the end of the string
}
return url.substring(pathStart, pathEnd);
}
String urlencode(String str)
{
String encodedString = "";
char c;
char code0;
char code1;
char code2;
for (int i = 0; i < str.length(); i++) {
c = str.charAt(i);
if (c == ' ') {
encodedString += '+';
} else if (isalnum(c) || c == '=') { // 保留等号
encodedString += c;
} else {
code1 = (c & 0xf) + '0';
if ((c & 0xf) > 9) {
code1 = (c & 0xf) - 10 + 'A';
}
c = (c >> 4) & 0xf;
code0 = c + '0';
if (c > 9) {
code0 = c - 10 + 'A';
}
code2 = '\0';
encodedString += '%';
encodedString += code0;
encodedString += code1;
//encodedString+=code2;
}
yield();
}
return encodedString;
}
};
String gen_params(const String &appid, const String &domain, const String &question) {
StaticJsonDocument<512> data;
data["header"]["app_id"] = appid;
data["header"]["uid"] = "1234";
JsonObject parameter = data["parameter"]["chat"];
parameter["domain"] = domain;
parameter["random_threshold"] = 0.5;
parameter["max_tokens"] = 2048;
parameter["auditing"] = "default";
data["payload"]["message"]["text"] = question;
String jsonStr;
serializeJson(data, jsonStr);
return jsonStr;
}
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
Serial.println();
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED)
{
delay(500);
Serial.print(".");
}
Serial.println("WiFi connected!");
// 从网络时间服务器上获取并设置时间
// 获取成功后芯片会使用RTC时钟保持时间的更新
configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
Ws_Param wsParam(appid, api_key, api_secret, Spark_url);
String url = wsParam.create_url();
Serial.print("url:");
Serial.println(url);
}
void loop() {
}