名词解释
AliOS Things: 阿里云智能IoT团队自研的物联网操作系统
HaaS:全称是Hardware as a Service,阿里云智能IoT团队基于AliOS Things系统推出的硬件即服务
HaaS UI:全称是Hardware as a Service User Interface,是源自AliOS Things操作系统上的一套应用&图形解决方案,支持C/C++和 JS两种开发语言
1、HaaS UI JSAPI扩展
HaaS UI内置的JSAPI为虽然JS提供了调用底层系统能力的接口,例如数据存储、网络管理、文件操作等,但是这些内置的JSAPI不能满足用户所有的开发需求。HaaS UI提供了扩展JSAPI的方法,用户可以根据项目需求和平台能力实现不同的扩展,以满足不同的功能需要。用户如果想要自定义一些JSAPI,可以按照本教程进行扩展。
1.1、扩展JSAPI教程
本节内容用于扩展HaaS UI的JSAPI,提供js的扩展能力,下面将介绍一个demo JSAPI的编写步骤。
接口编写时主要有以下步骤:
- 编写接口头文件和实现,以及接口的编译配置.
- 注册接口到小程序容器
- 修改小程序容器的编译配置,添加新增的jsapi模块
JSAPI工程目录:
aos.mk用于在alios things编译
├── jsapi_demo
├── ExtensionProxyBase.h
├── DemoApiExtension.cpp
├── DemoApiExtension.h
└── aos.mk
1.1.1 、重要说明
- 不论是接口还是事件,输入/输出的参数请确保为合法的json格式字符串
- 在回调中mProxy->postCallback(),方法必须执行,否则会导致内存泄露.就算没有返回值也必须调用.
- 接口定义参数为固定形式,只接收两个字符串类型参数,请参照testApi(const std::string& ,const std::string&)格式定义(不要修改定义)
1.1.2、 JSAPI方法实现
所有扩展的JSAPI在使用前需通过REGISTER_JSAPI()方法注册:
extensionProxy->REGISTER_JSAPI(&testApi, moduleName, testApi);
接口实现示例:
DemoApiExtension.h,依赖于ExtensionProxyBase.h:
#include "ExtensionProxyBase.h" // 扩展jsapi时需要include该头文件
using namespace ariver::iot;
namespace demo
{
/**
* 异步方法
* @param callbackid naitve回调js方法时的回调id
* @param params js调用native方法时的参数,json字符串
*/
void testApi1(const std::string& callbackid, const std::string& params);
/**
* 同步方法
* 同步方法和异步方法写法一模一样,区别在于上层js调用时是同步还是异步.
* @param callbackid naitve回调js方法时的回调id
* @param params js调用native方法时的参数,json字符串
*/
void testApi2(const std::string& callbackid, const std::string& params);
/**
* jsapi注册方法
*
*/
extern "C" void testapi_init_jsapis();
};
} // namespace demo
DemoApiExtension.cpp:
namespace falcon
{
/**
* @param callbackid 用于回调js
* @param params (必现是json格式)
*/
void testJSApi1(const std::string& callbackid, const std::string& params) // 异步方法
{
/* user code */
printf("Native testJSApi1 called params(%s).\n", params.c_str());
/* user code */
// callback
ariver::iot::ExtensionProxyBase* extensionProxy = ariver::iot::getJSApiExtensionProxy();
// 必须回调,成功返回成功,失败返回错误码
extensionProxy->postCallback(callbackid, ariver::iot::API_Success, "{\"result\": \"testJSApi1 call success\"}");
}
/**
* @param callbackid 用于回调js
* @param params (必现是json格式)
*/
void testApi2(const std::string& callbackid, const std::string& params) // 同步方法
{
printf("%s", ("testApi2 params:" + params + "\n").c_str());
/*
* 同步方法和异步方法写法一模一样,区别在于上层js调用时是同步还是异步.
*/
std::string cbParams = "{\"paramsToJs\":\"result2\", \"otherOutput\":222}";
// 必须回调,成功返回成功,失败返回错误码
mProxy->postCallback(callbackid, API_Success, cbParams);
}
// extern给容器调用初始化
extern "C" void testapi_init_jsapis()
{
ariver::iot::ExtensionProxyBase* extensionProxy = ariver::iot::getJSApiExtensionProxy();
// call from js like:
// import testapi from "$jsapi/testapi";
// testapi.testJSApi1({}, r => {});
extensionProxy->REGISTER_JSAPI(&testJSApi1, testapi, testJSApi1);
// param1: apiFunction, param2: module, param3: apiName
}
}
ExtensionProxyBase.h:
#include <string>
#include <stdio.h>
#include <map>
namespace ariver
{
namespace iot
{
enum APIStatus {
API_Success = 0,
API_NotSupport = 1, // 无效的api调用
API_ParamError = 2, // 无效的参数
API_Failed = 3,
API_NoPermission = 4,
API_Timeout,
API_UserDenied,
API_UserCancelled = 11,
};
class ExtensionProxyBase
{
public:
typedef void (*InvokeFunction)(const std::string& callbackid, const std::string& params);
/**
* @deprecated
* 后续会废弃,使用REGISTER_MODULE_JSAPI替代
*
* 业务方扩展JSAPI使用该接口注册
* func: jsapi具体的实现函数
* label_name: 映射到js端的函数名称,如$falcon.jsapi.alert label_name=alert
*/
#define REGISTER_STD_JSAPI(func, label_name) \
registerJSApi(func, #label_name);
/**
* 业务方扩展JSAPI使用该接口注册
* func: jsapi具体的实现函数
* module: 模块名,映射到js端的模块名称,如$falcon.jsapi.module
* label_name: 映射到js端的函数名称,如$falcon.jsapi.module.alert label_name=alert
*/
#define REGISTER_JSAPI(func, module, label_name) \
registerJSApi(func, #module, #label_name);
/**
* @deprecated
*/
virtual void registerJSApi(InvokeFunction func, const std::string& labelName) = 0;
/**
* 业务方扩展JSAPI使用该接口注册
* func: jsapi具体的实现函数
* module: 模块名,映射到js端的模块名称,如$falcon.jsapi.module
* label_name: 映射到js端的函数名称,如$falcon.jsapi.module.alert label_name=alert
*/
virtual void registerJSApi(InvokeFunction func, const std::string& module, const std::string& labelName) = 0;
/**
* Jsapi回调函数
* callbackId: 如容器侧未下传callbackid,需要在jsapi extension实现侧自行生成
*/
virtual void postCallback(const std::string& callbackid, APIStatus status, const std::string& params) = 0;
/**
* 容器上行发送自定义事件的接口
* js端使用 $falcon.on("customEvent", (param)=>{}) 注册
* customEvent: 事件名称
* param: 参数
*/
virtual void sendCustomEvent(const std::string& customEvent, const std::string& param) = 0;
/**
* 容器上行发送自定义事件的接口
* js端使用方法
* import module from "$jsapi/moduleName"
* module.on("customEvent", (param)=>{})
* 进行注册
*
* module: 模块名称
* customEvent: 事件名称
* param: 参数
*/
virtual void sendCustomEvent(const std::string& module, const std::string& customEvent, const std::string& param) = 0;
};
ExtensionProxyBase* getJSApiExtensionProxy();
} // namespace iot
} // namespace ariver
1.1.3、 添加接口目录下的编译文件
aos.mk
$(NAME)_MBINS_TYPE := share
$(NAME)_VERSION := 0.0.1 #版本号
$(NAME)_SUMMARY := jsapi demo #改为自己的模块描述
$(NAME)_INCLUDES += ./ #include路径
$(NAME)_SOURCES += DemoApiExtension.cpp #源码列表
1.1.4、 向小程序容器注册接口
在容器初始化之前实例化JSAPI接口,在JSApilniter.cpp中调用初始化接口:
testapi_init_jsapis();
1.1.5、 修改JSAPI工程根目录下的编译文件
文件:jsapi/aos.mk
$(NAME)_MBINS_TYPE := share
$(NAME)_VERSION := 0.0.1
$(NAME)_SUMMARY := jsapi lib
$(NAME)_INCLUDES += ../common/include ./
$(NAME)_COMPONENTS += jsapi_demo
$(NAME)_COMPONENTS += jsapi_wifi
$(NAME)_COMPONENTS += jsapi_new #添加新增的接口模块
...
1.2、 扩展JSAPI调用
HaaS UI中的扩展jsapi接口挂载于$falcon.jsapi对象下,所有的扩展jsapi接口均可通过该对象访问.
调用jsapi将返回一个Promise对象 ,可通过callback回调,也可通过await等待请求返回.
$falcon.jsapi.testApi({}, (params) => {
console.log("callback", params);
});
// 2.带模块名的api(推荐使用带模块名的api)
// 示例的模块名为testapi
const testapi = $falcon.jsapi.testapi;
// 通过callback回调
testapi.testApi({}, (params) => {
console.log("callback", params);
});
// 或者使用await,需要在async方法中调用
const result = await testapi.testApi({});
if (result && result.error) {
console.log('jsapi failed, error=', result.error);
} else {
console.log('jsapi succeed', result);
}
2、开发者技术支持
如需更多技术支持,可加入钉钉开发者群,或者关注微信公众号
更多技术与解决方案介绍,请访问阿里云AIoT首页https://iot.aliyun.com/