FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

NebulaGate/bemfa-sdk: 巴法云(Bemfa)Java & Android SDK,轻松接入,开箱即用,请求成功直接返回业务数据,无需手动解析 JSON。基于 SPI 跨平台设计,还支持 Android 生命周期自动取消请求。已发布 Maven Central:io.github.nebulagate · GitHub

Repository files navigation

Bemfa SDK

巴法云(Bemfa)的 Java / Android SDK —— 轻松接入,开箱即用!

👋 你好,我是一名高中生,这个 SDK 是我在课余时间从零开始写的。如果它对你有帮助,希望能点个⭐Star 支持一下 —— 你的鼓励是我继续学习和维护的动力!

📡 国内用户请注意

  • 提 Bug、建议或 PR → GitHub 与 Gitee 两个仓库都开放 Issues,国内访问慢可走 Gitee 仓库,习惯 GitHub 的也可走 GitHub 仓库
  • 点 Star 支持我 → 请到 GitHub 仓库

简单说:Issue / PR 双平台都欢迎,Star 走 GitHub。感谢你的支持!


目录


项目简介

Bemfa SDK 是 巴法科技&巴法云 物联网平台的 Java / Android 开发工具包。它把巴法云的 REST API 封装成类型安全的 Java 接口,你用 Builder 链式调用构建请求,拿到的就是解析好的业务对象,不用自己拼 URL、不用手写 JSON 解析。

树莓派上跑 Java 也行,Android 手机上写 IoT 控制器也行,API 调用方式不变,业务模型不变,SDK 自己适配当前平台。后续有时间会更新 TCP 长连接和 MQTT 协议。


适合谁使用

Bemfa SDK 的设计目标是「轻量、好上手」,所以在下面几类场景里最能发挥作用:

  • 学生与学习者:无论是课程设计、毕业设计、电子类竞赛,还是刚入门想做个物联网小作品,都可以用 SDK 避开 HTTP 请求、JSON 解析、错误码判断这些琐碎活儿,把精力集中在自己的业务逻辑上。
  • 物联网爱好者 / Maker:玩树莓派、智能家居 DIY,或用 Java 联动巴法云的主题、设备、定时器,强类型 API 能让你的脚本或 App 写得又快又稳。
  • 个人开发者与独立创作者:做个人项目、小工具、Demo 演示时,几行代码就能接入巴法云,不用重复造轮子(这也是我开发这个项目的初衷)。

💡 本项目由个人开发者利用课余时间维护,更适合学习、原型验证与个人项目。如果你打算用于正式生产环境,建议先充分测试、并结合自身需求评估。


核心亮点

1. 开箱即用的业务数据

正常调 REST API,你得自己接 HTTP 响应、解 JSON、判错误码、抠业务字段。然而 Bemfa SDK 把这些全包了:

// ...

// 请求成功 = 拿到业务数据,就这么简单
TopicInfo topic = client.executeSync(
    BemfaRequestApis.v1.Device.getTopicApiBuilder()
        .topicId("yourTopic")
        .topicType(TopicType.MQTT)
        .build()
);
// topic 已经是强类型对象,可以直接使用
System.out.println(topic.getNickname());

SDK 内部有 6 种 ResponseHandler 覆盖巴法云所有响应格式,像 JSON 解析、错误码判断、类型转换等等,这些全都由 SDK 自动完成。你拿到的不是解析好的业务对象,就是带明确原因的异常。

2. SPI 跨平台架构

SDK 用 SPI(Service Provider Interface)机制做了平台无关的架构:

bemfa-api             公开 API 层(接口、模型、注解),所有平台共享
  ├── bemfa-core      核心实现层(HTTP 引擎、响应处理器)
  ├── bemfa-jvm       JVM 平台适配(SPI 注册:JvmBemfaServiceProvider)
  └── bemfa-android   Android 平台适配(SPI 注册:AndroidBemfaServiceProvider)

启动时,BemfaServiceLoader 自动检测当前运行环境(JVM 还是 Android),加载对应的 BemfaServiceProvider。你不用指定平台,也不用写 if (isAndroid()) 之类的判断,引入对应平台的依赖就行,SDK 自己找。

以后要加新平台(比如鸿蒙),只需加一个 Provider 实现就够了,上层 API 不用动。

⚠️ 已知设计缺陷:配置的构建与获取尚未实现平台无感知

使用 SPI 架构的初衷是让接入者完全不需要关心当前跑在什么平台——HTTP 客户端的选择、服务发现都已经做到了自动适配。但配置这块还有一个没跨过去的坎:

问题一:构建配置时需要自己选平台类

// JVM 环境
BemfaConfig config = new BemfaConfig();

// Android 环境 — 必须用 AndroidBemfaConfig,否则拿不到平台专属功能
AndroidBemfaConfig config = new AndroidBemfaConfig();

问题二:获取配置时也需要传入平台类

// JVM 环境
BemfaConfig config = BemfaClient.getConfig(BemfaConfig.class);

// Android 环境 — 必须传 AndroidBemfaConfig.class
AndroidBemfaConfig config = BemfaClient.getConfig(AndroidBemfaConfig.class);

理想情况下,这两步都应该由 SDK 内部自动判断平台、返回正确的配置类型,接入者完全不需要感知——就像引入依赖后 SDK 自动选择 HTTP 客户端一样。但由于 Java 类型擦除和静态构造的限制,我确实还没有找到合适的实现方式,暂时只能麻烦接入者自行判断平台。

如果你有解决思路或建议,非常欢迎在 Gitee IssueGitHub Issue 中指教,不胜感激!

3. HTTP 请求与 Android 生命周期自动管理

Activity 销毁了但网络请求还在跑,这事在 Android 开发里挺常见,往往需要手动取消相应的请求,然而手动取消又麻烦又容易漏。对此,Bemfa SDK 提供了一个可选项:

// 初始化时开启
AndroidBemfaConfig config = new AndroidBemfaConfig();
config.setHttpLifecycleAutoManaged(true);
BemfaClient.init(config);

// 也可以动态调整
BemfaClient.getConfig(AndroidBemfaConfig.class).setHttpLifecycleAutoManaged(true);

// 请求时把 Activity 作为 tag 传入
String time = http.executeSync(api, MainActivity.this);                       
// Activity 销毁时,SDK 将自动取消该 Activity 名下的所有在途请求

开启后,LifecycleRequestManager 监听 LifecycleOwner 的 ON_DESTROY 事件,自动取消以该 Activity 为 tag 的所有在途请求。接入者的 onDestroy() 里不用写取消逻辑了。

💡 注意:默认为关闭状态。JVM 环境不受影响。


模块架构

bemfa-sdk
├── bemfa-api            公开 API 层:BemfaClient、BemfaConfig、BemfaRequestApis、业务数据模型、异常、错误码等
├── bemfa-core           核心实现层
├── bemfa-jvm            JVM 平台适配:引入此模块即可在 JVM 环境使用
├── bemfa-android        Android 平台适配:引入此模块即可在 Android 环境使用
├── bemfa-test-jvm       JVM 测试程序,主要测试各 HTTP 请求 API 的可用性
└── bemfa-test-android   Android 测试程序,主要测试 HTTP 请求的生命周期自动管理
你的环境 需要引入的模块
JVM(服务端、树莓派等) bemfa-api + bemfa-jvm
Android bemfa-api + bemfa-android

bemfa-core 会被平台模块自动引入,无需单独依赖。


快速开始

JVM 环境

1. 添加依赖

dependencies {
    implementation('io.github.nebulagate:bemfa-api:1.0.0')
    implementation('io.github.nebulagate:bemfa-jvm:1.0.0')
}

坐标已发布至 Maven Central,无需像 JitPack 那样额外配置仓库。如果你使用 Maven 构建,等效配置如下(pom.xml):

<dependency>
    <groupId>io.github.nebulagate</groupId>
    <artifactId>bemfa-api</artifactId>
    <version>1.0.0</version>
</dependency>
<dependency>
    <groupId>io.github.nebulagate</groupId>
    <artifactId>bemfa-jvm</artifactId>
    <version>1.0.0</version>
</dependency>
💡 关于 SLF4J 日志绑定(JVM)

bemfa-jvm 默认已绑定 slf4j-jdk14(JDK 自带日志框架),引入依赖后无需额外配置即可输出 SDK 日志。

如果你已在项目中接入了其他基于 SLF4J 的日志框架(如 Logback、Log4j2),需要排除 SDK 默认的绑定、再引入你自己的绑定,否则会出现「SLF4J 检测到多个绑定」的冲突警告:

implementation('io.github.nebulagate:bemfa-jvm:1.0.0') {
    exclude group: 'org.slf4j', module: 'slf4j-jdk14'
}

slf4j-api 门面由 bemfa-api 自动传递引入,你无需手动声明;需要管理的只是「绑定」这一层。

2. 初始化 SDK

BemfaConfig config = new BemfaConfig();
config.setLogLevel(LogLevel.INFO);
BemfaClient.init(config);

3. 登录并发起请求

HttpClient client = BemfaClient.getHttpClient();

// 使用手机号登录(还支持邮箱登录)
client.executeSync(
    BemfaRequestApis.v1.User.loginWithPhoneApiBuilder()
        .phone("yourPhone")
        .password("yourPassword")
        .area("86")
        .build()
);
// 也可以使用 UID 登录
// BemfaClient.loginByUid("yourUid");

// 创建设备主题
client.executeSync(
    BemfaRequestApis.v1.Device.createTopicApiBuilder()
        .topicId("yourTopic")
        .topicType(TopicType.MQTT)
        .nickname("客厅灯")
        .build()
);

// 获取所有主题,直接拿到 TopicInfos 对象,不用解析 JSON
TopicInfos topics = client.executeSync(
    BemfaRequestApis.v1.Device.getAllTopicApiBuilder()
        .topicType(TopicType.MQTT)
        .build()
);

// 推送消息
client.executeSync(
    BemfaRequestApis.v1.Device.pushMessageApiBuilder()
        .topicId("yourTopic")
        .topicType(TopicType.MQTT)
        .message("开灯")
        .build()
);

// ...

4. 关闭 SDK

BemfaClient.close();

Android 环境

1. 添加依赖

dependencies {
    implementation('io.github.nebulagate:bemfa-api:1.0.0')
    implementation('io.github.nebulagate:bemfa-android:1.0.0')
}

坐标已发布至 Maven Central,无需像 JitPack 那样额外配置仓库。Android 项目通常用 Gradle,如果你使用 Maven 构建,等效配置如下(pom.xml):

<dependency>
    <groupId>io.github.nebulagate</groupId>
    <artifactId>bemfa-api</artifactId>
    <version>1.0.0</version>
</dependency>
<dependency>
    <groupId>io.github.nebulagate</groupId>
    <artifactId>bemfa-android</artifactId>
    <version>1.0.0</version>
</dependency>

📌 AndroidX 依赖:由于 SDK 的 Android 模块使用了 AndroidX 的 Lifecycle 特性,目前仅支持 AndroidX 项目集成。若你的项目仍在使用旧版 Support Library(android.support.*),需先迁移到 AndroidX 才能接入 bemfa-android。

💡 关于 SLF4J 日志绑定(Android)

bemfa-android 默认已绑定 slf4j-android(输出到 Android Logcat),引入依赖后无需额外配置即可输出 SDK 日志。

如果你已在项目中接入了其他基于 SLF4J 的日志框架(如 Logback-Android),需要排除 SDK 默认的绑定、再引入你自己的绑定,否则会出现「SLF4J 检测到多个绑定」的冲突警告:

implementation('io.github.nebulagate:bemfa-android:1.0.0') {
    exclude group: 'org.slf4j', module: 'slf4j-android'
}

slf4j-api 门面由 bemfa-api 自动传递引入,你无需手动声明;需要管理的只是「绑定」这一层。

📌 混淆(R8 / ProGuard):SDK 已通过 consumer-rules.pro 内置混淆规则,开启混淆的 Release 构建会自动合并 SDK 内置的 -keep 规则。

2. 初始化(可开启生命周期管理)

AndroidBemfaConfig config = new AndroidBemfaConfig();
config.setHttpLifecycleAutoManaged(true);  // 开启后请求自动跟随 Activity 生命周期
BemfaClient.init(config);

3. 登录

// 防止线程阻塞,需在后台线程执行 HTTP 请求
new Thread(() -> {
    // 手机号登录(还支持邮箱登录)
    BemfaClient.getHttpClient().executeSync(
        BemfaRequestApis.v1.User.loginWithPhoneApiBuilder()
            .phone("yourPhone")
            .password("yourPassword")
            .area("86")
            .build()
    );
}).start();

// 也可以使用 UID 登录:
// BemfaClient.loginByUid("yourUid");

4. 在后台线程发起请求(自动跟随生命周期)

new Thread(() -> {
    try {
        HttpClient http = BemfaClient.getHttpClient();

        // 获取主题信息,直接拿到强类型 TopicInfo 对象,不用解析 JSON
        TopicInfo topic = http.executeSync(
            BemfaRequestApis.v1.Device.getTopicApiBuilder()
                .topicId("yourTopic")
                .topicType(TopicType.MQTT)
                .build(),
            MainActivity.this   // 传入 Activity 作为 tag,页面销毁时自动取消请求
        );

        runOnUiThread(() -> textView.setText("主题昵称:" + topic.getNickname()));
    } catch (RequestCanceledException e) {
        // 页面已销毁,请求被自动取消,无需处理
    } catch (BemfaSdkException e) {
        // 其他 SDK 异常(网络 / 业务 / HTTP 等)统一兜底
        runOnUiThread(() -> showError(e));
    }
}).start();

5. 异步请求(回调在后台线程,UI 需切回主线程)

// 异步调用本身可在主线程发起;回调运行在后台线程,更新 UI 需 runOnUiThread 包起来
BemfaClient.getHttpClient().executeAsync(
    BemfaRequestApis.v1.Device.getTopicApiBuilder()
        .topicId("yourTopic")
        .topicType(TopicType.MQTT)
        .build(),
    new RequestCallback<TopicInfo>() {
        @Override
        public void onSuccess(TopicInfo topic) {
            runOnUiThread(() -> textView.setText("主题昵称:" + topic.getNickname()));
        }

        @Override
        public void onError(BemfaSdkException e) {
            runOnUiThread(() -> textView.setText("请求失败:" + e.getMessage()));
        }
    }
);

6. 关闭 SDK

BemfaClient.close();

HTTP 请求 API 参考

API 一览

SDK 对巴法云 API 按功能重新进行了分类,提供集中访问点(BemfaRequestApis 类),全部使用 Builder 模式链式构建:

分类 模块入口 代表性 API
设备管理 BemfaRequestApis.v1.Device 创建/删除主题、获取主题列表、推送消息、修改分组/房间、修改主题昵称、获取主题昵称
用户认证 BemfaRequestApis.v1.User 手机/邮箱注册、手机/邮箱登录、创建/查询/删除 AppId
定时任务 BemfaRequestApis.v1.Timer 添加/查询/启用/禁用/删除定时器
图片管理 BemfaRequestApis.v1.Image 上传图片、获取图片列表、删除图片
微信通知 BemfaRequestApis.v1.WeChat 发送微信提醒/告警
设备分享 BemfaRequestApis.v1.Share 分享主题、查询分享记录、取消分享
固件 OTA BemfaRequestApis.v1.Firmware 获取/上传固件
语音上传 BemfaRequestApis.v1.Voice 上传语音文件
网络校时 BemfaRequestApis.v1.Time 获取服务端时间

返回值都是强类型 Java 对象(TopicInfo、TimerInfos、ImageInfo、FirmwareInfo 等),不是 JSON 字符串。

📌 API 版本说明

当前 SDK 基于 2026 年 1 月 10 日巴法云官方 API 文档实现,暂未同步最新版本。完整 API 文档请参考 巴法云 HTTP 请求 API 文档 — 2026.1.10(PDF)

作者学业繁忙,后续会尽量抽时间更新,感谢理解与耐心。

API 构建方式

// 一:使用集中访问点(推荐)
BemfaRequestApi<Void> apiA = BemfaRequestApis.v1.User.loginWithPhoneApiBuilder()
        .phone("yourPhone")
        .password("yourPassword")
        .area("86")
        .build();
// 或者
LoginWithPhoneApi apiB = BemfaRequestApis.v1.User.loginWithPhoneApiBuilder()
        .phone("yourPhone")
        .password("yourPassword")
        .area("86")
        .build();

// 二:直接使用相应的 API Builder
LoginWithPhoneApi apiC = LoginWithPhoneApi.builder()
        .phone("yourPhone")
        .password("yourPassword")
        .area("86")
        .build();
// 或者
LoginWithPhoneApi apiD = LoginWithPhoneApi.loginWithPhoneApiBuilder()
        .phone("yourPhone")
        .password("yourPassword")
        .area("86")
        .build()

// 三:当然你也可以直接在执行请求方法中构建 API
BemfaClient.getHttpClient().executeSync(BemfaRequestApis.v1.User.loginWithPhoneApiBuilder()
        .phone("yourPhone")
        .password("yourPassword")
        .area("86")
        .build());

同步与异步

同步和异步都能用:

HttpClient client = BemfaClient.getHttpClient();
BemfaRequestApi<String> api = BemfaRequestApis.v1.Time
        .getCurrentTimeApiBuilder()
        .type(1)
        .build();

// 同步:阻塞当前线程,直接返回结果,可 try-catch 捕获相关异常
String time = client.executeSync(api);

// 异步:不阻塞,结果在回调中返回
client.executeAsync(api, new RequestCallback<String>() {
    @Override
    public void onSuccess(String result) {
        System.out.println("成功:" + result);
    }

    @Override
    public void onBusinessError(BemfaSdkErrorCode errorCode, ApiBusinessException e) {
        System.err.println("业务错误:" + e.getMessage());
    }

    @Override
    public void onNetworkError(NetworkException e) {
        System.err.println("网络错误:" + e.getMessage());
    }

    @Override
    public void onResponseParseError(String responseBody, ApiResponseException e){
        System.err.println("响应解析错误:" + e.getMessage());
    }

    @Override
    public void onError(BemfaSdkException e) {
        System.err.println("其他错误:" + e.getMessage());
    }
});
// 如果对请求产生的错误不关心,也可以只实现回调接口的成功方法
client.executeAsync(api, new RequestCallback<String>() {
    @Override
    public void onSuccess(String result) {
        System.out.println("成功:" + result);
    }
});

⚠️ 注意(Android 线程模型)

  • 同步 executeSync:会阻塞当前线程,在 Android 上必须在后台线程执行
  • 异步 executeAsync:调用本身可在主线程发起(网络由 SDK 内部线程池执行,不阻塞);但回调 RequestCallback 运行在后台线程,回调内更新 UI 必须用 runOnUiThread(...) 包起来。

错误处理

错误分了几层,最终都落到 BemfaSdkErrorCode 枚举或对应的异常类型:

错误类型 异常类 说明
参数校验错误 InvalidArgumentException 构建请求时参数不合法(错误码 -100)
网络连接错误 NetworkException 无网络、连接超时等(错误码 -300)
HTTP 状态错误 ApiHttpException 服务器返回非 2xx 状态码
响应解析错误 ApiResponseException 响应体格式异常、JSON 解析失败(错误码 -200);non-void API 返回空响应体也会抛此异常
请求被取消 RequestCanceledException 请求在返回前被取消(生命周期销毁或手动 cancelByTag 等方式取消);同步直接抛出,异步经 onError 回调
业务逻辑错误 ApiBusinessException 后端返回的业务错误码(正数,如 40004 主题不存在)
客户端状态错误 IllegalClientStateException 未登录
未初始化错误 UninitializedException 未初始化 SDK
SPI 错误 ServiceProviderException 平台适配器加载失败(错误码 -400)

异步回调里,RequestCallback 有几个分类的错误处理方法(onBusinessError、onNetworkError、onResponseParseError 等),onError 兜底所有情况。被取消的请求在异步中也会走 onError(携带 RequestCanceledException),在同步中则直接抛出 RequestCanceledException —— 因此同步调用需用 try-catch 捕获,异步调用在 onError 中即可统一处理。


关于作者

你好,我是这个项目的作者,目前就读高二,即将步入高三。

写这个 SDK 的原因挺简单的:我自己用巴法云的时候,觉得每次都要手动拼 URL、解析 JSON、处理各种格式不一样的响应体,既麻烦,又容易出错,让人烦躁。然后就想做一套简单易用的 SDK,让接入巴法云的人更省心,请求成功直接拿到业务数据,开箱即用。于是就从高一寒假开始,断断续续写到了现在。

坦白说,这是我在课余时间独立完成的项目,代码和架构上难免有不成熟的地方:

  • 部分功能、文档和测试仍在完善中,一些边界情况可能尚未覆盖到。
  • 即将步入高三,学业紧张,更新维护节奏会比较慢,Issue 回复可能不够及时,恳请见谅。
  • 欢迎大家提出建议和批评,我会虚心学习、持续改进。

如果你在使用中遇到了问题,或者有好的想法,可随时前往 Gitee 仓库(国内访问快)或 GitHub 仓库 提 Issue / PR;如果这个 SDK 能对你有所帮助,那就是我最开心的事了 —— 也希望你抽空到 GitHub 点个 ⭐ Star,这对一个高中生开发者来说是莫大的鼓励。

联系方式

如果你在使用中遇到问题,或想交流想法,欢迎通过以下方式联系我。

渠道 地址
Gitee Issues(国内推荐) Gitee Issues
GitHub Issues GitHub Issues
QQ 3446936953
QQ 交流群 246394085
邮箱 nebulagate@foxmail.com
CSDN 博客 云阙(NebulaGate)

扫码快速联系

QQ 二维码 QQ 交流群二维码

设计参考与致谢

本项目的部分设计思路参考了社区优秀的开源实践,特此致谢:

  • SPI 跨平台架构 —— 灵感来自 SLF4J 日志框架 通过 ServiceLoader 解耦 API 与具体实现的思路;
  • HTTP 请求生命周期自动管理 —— 设计思路参考了 EasyHttp(作者:Android 轮子哥 @getActivity)等 Android 网络库的 Lifecycle 管理方案。

作为一个初学者,能站在这些优秀开源作品的肩膀上学习和实践,是我的荣幸。真诚感谢作者们的无私分享。


免责声明

  • 本项目仅供学习与交流使用,严禁用于任何非法用途,违者后果自负。
  • 本项目已获巴法云官方发布支持,由社区独立开发与维护。
  • 转载请注明出处,感谢尊重。

About

巴法云(Bemfa)Java & Android SDK,轻松接入,开箱即用,请求成功直接返回业务数据,无需手动解析 JSON。基于 SPI 跨平台设计,还支持 Android 生命周期自动取消请求。已发布 Maven Central:io.github.nebulagate

Topics

Resources

Stars

2 stars

Watchers

1 watching

Forks

Releases

Contributors

Languages


Back | FazBrowse Home | New Git URL