* Copyright (c) 2024 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <new>
#include "wifi_napi_device.h"
#include "inner_api/plugin_utils_napi.h"
#include "log.h"
#include "wifi_callback.h"
#include "wifi_device.h"
#include "wifi_napi_errcode.h"
namespace OHOS::Plugin {
std::shared_ptr<WifiDevice> wifiDevicePtr = WifiDevice::GetInstance(0);
static std::set<std::string> g_supportEventList = {
EVENT_STA_POWER_STATE_CHANGE,
EVENT_STA_CONN_STATE_CHANGE,
};
std::map<std::string, std::int32_t> g_EventSysCapMap = {
{ EVENT_STA_POWER_STATE_CHANGE, SYSCAP_WIFI_STA },
{ EVENT_STA_CONN_STATE_CHANGE, SYSCAP_WIFI_STA },
};
static void LinkedInfoToJs(const napi_env& env, WifiLinkedInfo& linkedInfo, napi_value& result)
{
SetValueUtf8String(env, "ssid", linkedInfo.ssid.c_str(), result);
SetValueUtf8String(env, "bssid", linkedInfo.bssid.c_str(), result);
SetValueInt32(env, "networkId", linkedInfo.networkId, result);
SetValueInt32(env, "rssi", linkedInfo.rssi, result);
SetValueInt32(env, "band", linkedInfo.band, result);
SetValueInt32(env, "linkSpeed", linkedInfo.linkSpeed, result);
SetValueInt32(env, "frequency", linkedInfo.frequency, result);
SetValueBool(env, "isHidden", linkedInfo.ifHiddenSSID, result);
SetValueBool(env, "isRestricted", linkedInfo.isDataRestricted, result);
SetValueInt32(env, "chload", linkedInfo.chload, result);
SetValueInt32(env, "snr", linkedInfo.snr, result);
SetValueUtf8String(env, "macAddress", linkedInfo.macAddress.c_str(), result);
SetValueInt32(env, "macType", linkedInfo.macType, result);
SetValueUnsignedInt32(env, "ipAddress", linkedInfo.ipAddress, result);
SetValueInt32(env, "suppState", static_cast<int>(linkedInfo.supplicantState), result);
SetValueInt32(env, "connState", static_cast<int>(linkedInfo.connState), result);
SetValueInt32(env, "WifiStandard", static_cast<int>(linkedInfo.wifiStandard), result);
SetValueInt32(env, "maxSupportedRxLinkSpeed", static_cast<int>(linkedInfo.maxSupportedRxLinkSpeed), result);
SetValueInt32(env, "maxSupportedTxLinkSpeed", static_cast<int>(linkedInfo.maxSupportedTxLinkSpeed), result);
SetValueInt32(env, "rxLinkSpeed", static_cast<int>(linkedInfo.rxLinkSpeed), result);
SetValueInt32(env, "txLinkSpeed", static_cast<int>(linkedInfo.txLinkSpeed), result);
SetValueInt32(env, "channelWidth", static_cast<int>(linkedInfo.channelWidth), result);
}
napi_value GetLinkedInfo(napi_env env, napi_callback_info info)
{
TRACE_FUNC_CALL;
size_t argc = 2;
napi_value argv[argc];
napi_value thisVar = nullptr;
void* data = nullptr;
NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, &data));
WIFI_NAPI_ASSERT(env, wifiDevicePtr != nullptr, WIFI_OPT_FAILED, SYSCAP_WIFI_STA);
LinkedInfoAsyncContext* asyncContext = new LinkedInfoAsyncContext(env);
WIFI_NAPI_ASSERT(env, asyncContext != nullptr, WIFI_OPT_FAILED, SYSCAP_WIFI_STA);
napi_create_string_latin1(env, "getLinkedInfo", NAPI_AUTO_LENGTH, &asyncContext->resourceName);
asyncContext->executeFunc = [&](void* data) -> void {
LinkedInfoAsyncContext* context = static_cast<LinkedInfoAsyncContext*>(data);
TRACE_FUNC_CALL_NAME("wifiDevicePtr->GetLinkedInfo");
context->errorCode = wifiDevicePtr->GetLinkedInfo(context->linkedInfo);
};
asyncContext->completeFunc = [&](void* data) -> void {
LinkedInfoAsyncContext* context = static_cast<LinkedInfoAsyncContext*>(data);
napi_create_object(context->env, &context->result);
LinkedInfoToJs(context->env, context->linkedInfo, context->result);
LOGI("Push get linkedInfo result to client");
};
size_t nonCallbackArgNum = 0;
asyncContext->sysCap = SYSCAP_WIFI_STA;
return DoAsyncWork(env, asyncContext, argc, argv, nonCallbackArgNum);
}
napi_value IsWifiActive(napi_env env, napi_callback_info info)
{
TRACE_FUNC_CALL;
WIFI_NAPI_ASSERT(env, wifiDevicePtr != nullptr, WIFI_OPT_FAILED, SYSCAP_WIFI_STA);
bool activeStatus = false;
ErrCode ret = wifiDevicePtr->IsWifiActive(activeStatus);
if (ret != WIFI_OPT_SUCCESS) {
LOGE("Get wifi active status fail: %{public}d", ret);
WIFI_NAPI_ASSERT(env, ret == WIFI_OPT_SUCCESS, ret, SYSCAP_WIFI_STA);
}
napi_value result;
napi_get_boolean(env, activeStatus, &result);
return result;
}
napi_value IsConnected(napi_env env, napi_callback_info info)
{
TRACE_FUNC_CALL;
WIFI_NAPI_ASSERT(env, wifiDevicePtr != nullptr, WIFI_OPT_FAILED, SYSCAP_WIFI_STA);
bool isConnected = false;
ErrCode ret = wifiDevicePtr->IsConnected(isConnected);
if (ret != WIFI_OPT_SUCCESS) {
LOGE("IsConnected return error: %{public}d", ret);
WIFI_NAPI_ASSERT(env, ret == WIFI_OPT_SUCCESS, ret, SYSCAP_WIFI_STA);
}
napi_value result;
napi_get_boolean(env, isConnected, &result);
return result;
}
napi_value On(napi_env env, napi_callback_info cbinfo)
{
TRACE_FUNC_CALL;
size_t requireArgc = 2;
size_t argc = 2;
napi_value argv[2] = { 0 };
napi_value thisVar = 0;
napi_valuetype valuetype;
NAPI_CALL(env, napi_get_cb_info(env, cbinfo, &argc, argv, &thisVar, nullptr));
if (argc >= 2) {
NAPI_CALL(env, napi_typeof(env, argv[1], &valuetype));
if (valuetype != napi_function) {
LOGI("callback Wrong argument type. Function expected.");
return nullptr;
}
}
if (requireArgc > argc) {
LOGI("requireArgc:%{public}zu, argc:%{public}zu", requireArgc, argc);
WIFI_NAPI_RETURN(env, false, WIFI_OPT_INVALID_PARAM, 0);
}
napi_valuetype eventName = napi_undefined;
napi_typeof(env, argv[0], &eventName);
if (eventName != napi_string) {
LOGI("first argv != napi_string");
WIFI_NAPI_RETURN(env, false, WIFI_OPT_INVALID_PARAM, 0);
}
napi_valuetype handler = napi_undefined;
napi_typeof(env, argv[1], &handler);
if (handler != napi_function) {
LOGI("second argv != napi_function");
WIFI_NAPI_RETURN(env, false, WIFI_OPT_INVALID_PARAM, 0);
}
std::string type = PluginUtilsNApi::GetStringFromValueUtf8(env, argv[0]);
if (type != EVENT_STA_POWER_STATE_CHANGE && type != EVENT_STA_CONN_STATE_CHANGE) {
LOGI("wifi event type error !");
return nullptr;
}
bool isWifiRegister = WifiCallback::GetInstance().HasWifiRegister(type);
WifiCallback::GetInstance().RegisterCallback(env, argv[1], type);
if (!isWifiRegister) {
ErrCode ret = wifiDevicePtr->On(type);
if (ret != WIFI_OPT_SUCCESS) {
LOGE("On return error: %{public}d", ret);
WIFI_NAPI_ASSERT(env, ret == WIFI_OPT_SUCCESS, ret, SYSCAP_WIFI_STA);
return nullptr;
}
}
napi_value result = nullptr;
napi_get_undefined(env, &result);
return result;
}
napi_value Off(napi_env env, napi_callback_info cbinfo)
{
TRACE_FUNC_CALL;
size_t requireArgc = 1;
size_t requireArgcWithCb = 2;
size_t argc = 2;
napi_value argv[2] = { 0 };
napi_value thisVar = 0;
napi_valuetype valuetype;
NAPI_CALL(env, napi_get_cb_info(env, cbinfo, &argc, argv, &thisVar, nullptr));
if (argc >= WIFI_NAPI_MAX_PARA) {
NAPI_CALL(env, napi_typeof(env, argv[1], &valuetype));
if (valuetype != napi_function) {
LOGI("callback Wrong argument type. Function expected.");
return nullptr;
}
}
if (requireArgc > argc) {
LOGI("requireArgc:%{public}zu, argc:%{public}zu", requireArgc, argc);
WIFI_NAPI_RETURN(env, false, WIFI_OPT_INVALID_PARAM, 0);
}
napi_valuetype eventName = napi_undefined;
napi_typeof(env, argv[0], &eventName);
if (eventName != napi_string) {
LOGI("first argv != napi_string");
WIFI_NAPI_RETURN(env, false, WIFI_OPT_INVALID_PARAM, 0);
}
napi_valuetype handler = napi_undefined;
if (argc >= requireArgcWithCb) {
napi_typeof(env, argv[1], &handler);
if (handler != napi_function && handler != napi_null) {
LOGI("second argv != napi_function");
WIFI_NAPI_RETURN(env, false, WIFI_OPT_INVALID_PARAM, 0);
}
}
std::string type = PluginUtilsNApi::GetStringFromValueUtf8(env, argv[0]);
if (type != EVENT_STA_POWER_STATE_CHANGE && type != EVENT_STA_CONN_STATE_CHANGE) {
LOGI("wifi event type error !");
return nullptr;
}
WifiCallback::GetInstance().UnRegisterCallback(env, argv[1], type);
bool isWifiRegister = WifiCallback::GetInstance().HasWifiRegister(type);
if (!isWifiRegister) {
ErrCode ret = wifiDevicePtr->Off(type);
if (ret != WIFI_OPT_SUCCESS) {
LOGE("Off return error: %{public}d", ret);
WIFI_NAPI_ASSERT(env, ret == WIFI_OPT_SUCCESS, ret, SYSCAP_WIFI_STA);
return nullptr;
}
}
napi_value result = nullptr;
napi_get_undefined(env, &result);
return result;
}
}