├── android ├── gradle.properties ├── src │ └── main │ │ ├── res │ │ └── values │ │ │ └── strings.xml │ │ ├── AndroidManifest.xml │ │ └── java │ │ └── com │ │ └── tuya │ │ └── smart │ │ └── rnsdk │ │ ├── utils │ │ ├── ReactParamsCheck.kt │ │ ├── JsonUtils.kt │ │ ├── BridgeUtils.kt │ │ ├── Constant.kt │ │ └── TuyaReactUtils.kt │ │ ├── push │ │ └── TuyaPushModule.kt │ │ ├── home │ │ ├── TuyaRoomModule.kt │ │ ├── TuyaHomeMemberModule.kt │ │ ├── TuyaHomeManagerModule.kt │ │ └── TuyaHomeDataManagerModule.kt │ │ ├── message │ │ └── TuyaMessageModule.kt │ │ ├── TuyaReactPackage.kt │ │ ├── device │ │ ├── TuyaSingleTransferModule.kt │ │ ├── TuyaOTAModule.kt │ │ ├── TuyaGatewayModule.kt │ │ └── TuyaDeviceModule.kt │ │ ├── core │ │ └── TuyaCoreModule.kt │ │ ├── feedback │ │ └── TuyaFeedBackModule.kt │ │ ├── group │ │ └── TuyaGroupModule.kt │ │ └── timer │ │ └── TuyaTimerModule.kt ├── consumer-rules.pro ├── README.md ├── proguard-rules.pro └── build.gradle ├── .eslintrc.js ├── pic └── android1.png ├── .commitlintrc.json ├── ios ├── RNTuyaSdk.xcodeproj │ └── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist ├── RNTuyaSdk.xcworkspace │ └── contents.xcworkspacedata └── RNTuyaSdk │ ├── Utils │ ├── TuyaRNUtils+DeviceParser.m │ ├── Listener │ │ ├── TuyaRNGroupListener.h │ │ ├── TuyaRNEventEmitter.h │ │ ├── TuyaRNHomeManagerListener.h │ │ ├── TuyaRNHomeListener.h │ │ ├── TuyaRNDeviceListener.h │ │ ├── TuyaRNEventEmitter.m │ │ ├── TuyaRNHomeManagerListener.m │ │ ├── TuyaRNGroupListener.m │ │ └── TuyaRNHomeListener.m │ ├── TuyaRNUtils+Network.h │ ├── TuyaRNUtils+Cache.h │ ├── TuyaRNUtils.h │ ├── TuyaRNUtils.m │ ├── TuyaRNUtils+Cache.m │ ├── TuyaRNUtils+Network.m │ └── TuyaRNUtils+DeviceParser.h │ ├── Core │ ├── TuyaRNCoreModule.h │ └── TuyaRNCoreModule.m │ ├── Home │ ├── TuyaRNHomeModule.h │ ├── TuyaRNHomeMemberModule.h │ ├── TuyaRNHomeManagerModule.h │ ├── TuyaRNHomeDataManagerModule.h │ ├── TuyaRNHomeDataManagerModule.m │ ├── TuyaRNHomeManagerModule.m │ └── TuyaRNHomeMemberModule.m │ ├── User │ └── TuyaRNUserModule.h │ ├── Group │ ├── TuyaRNGroupModule.h │ └── TuyaRNGroupModule.m │ ├── Room │ ├── TuyaRNRoomModule.h │ └── TuyaRNRoomModule.m │ ├── Scene │ └── TuyaRNSceneModule.h │ ├── Timer │ ├── TuyaRNTimerModule.h │ └── TuyaRNTimerModule.m │ ├── GateWay │ ├── TuyaRNGatewayModule.h │ └── TuyaRNGatewayModule.m │ ├── ShareDevice │ └── TuyaRNShareModule.h │ ├── DeviceControl │ ├── TuyaRNDeviceModule.h │ └── TuyaRNDeviceModule.m │ ├── Feedback │ ├── TuyaRNFeedBackModule.h │ └── TuyaRNFeedBackModule.m │ ├── Activator │ ├── TuyaRNActivatorModule.h │ └── TuyaRNActivatorModule.m │ ├── BLEScanner │ ├── TuyaBLERNScannerModule.h │ └── TuyaBLERNScannerModule.m │ ├── MessageCenter │ ├── TuyaRNMessageModule.h │ └── TuyaRNMessageModule.m │ └── BLEActivator │ ├── TuyaBLERNActivatorModule.h │ └── TuyaBLERNActivatorModule.m ├── .editorconfig ├── src ├── index.ts ├── homeDataManager.ts ├── bridgeUtils.ts ├── ota.ts ├── homeManager.ts ├── homeMember.ts ├── activator.ts ├── home.ts ├── user.ts ├── device.ts └── timer.ts ├── .github └── workflows │ ├── lint.yml │ └── release.yml ├── .releaserc.json ├── RNTuyaSdk.podspec ├── tsconfig.json ├── LICENSE ├── .gitignore ├── package.json └── README.md /android/gradle.properties: -------------------------------------------------------------------------------- 1 | android.useAndroidX=true 2 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: '@volst', 3 | }; 4 | -------------------------------------------------------------------------------- /pic/android1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/owowagency/react-native-tuya/HEAD/pic/android1.png -------------------------------------------------------------------------------- /.commitlintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "@commitlint/config-conventional" 4 | ] 5 | } -------------------------------------------------------------------------------- /android/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | tuyasmart-sdk-react-native 3 | 4 | -------------------------------------------------------------------------------- /android/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | -------------------------------------------------------------------------------- /ios/RNTuyaSdk.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ios/RNTuyaSdk.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | 3 | 5 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | 12 | [*.md] 13 | trim_trailing_whitespace = false 14 | 15 | [*.pbxproj] 16 | indent_style = tabs 17 | -------------------------------------------------------------------------------- /ios/RNTuyaSdk/Utils/TuyaRNUtils+DeviceParser.m: -------------------------------------------------------------------------------- 1 | // 2 | // TuyaRNUtils+DeviceParser.m 3 | // TuyaRnDemo 4 | // 5 | // Created by 浩天 on 2019/3/4. 6 | // Copyright © 2019年 Facebook. All rights reserved. 7 | // 8 | 9 | #import "TuyaRNUtils+DeviceParser.h" 10 | 11 | @implementation TuyaRNUtils (DeviceParser) 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './activator'; 2 | export * from './bridgeUtils'; 3 | export * from './device'; 4 | export * from './home'; 5 | export * from './homeDataManager'; 6 | export * from './homeManager'; 7 | export * from './homeMember'; 8 | export * from './ota'; 9 | export * from './timer'; 10 | export * from './user'; 11 | -------------------------------------------------------------------------------- /ios/RNTuyaSdk.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ios/RNTuyaSdk/Utils/Listener/TuyaRNGroupListener.h: -------------------------------------------------------------------------------- 1 | // 2 | // TuyaRNGroupListener.h 3 | // TuyaRnDemo 4 | // 5 | // Created by Elon on 2019/3/7. 6 | // Copyright © 2019 Facebook. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface TuyaRNGroupListener : NSObject 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /.github/workflows/lint.yml: -------------------------------------------------------------------------------- 1 | name: Lint & Build 2 | 3 | on: [pull_request] 4 | 5 | jobs: 6 | build: 7 | runs-on: ubuntu-latest 8 | steps: 9 | - uses: actions/checkout@v4 10 | - uses: actions/setup-node@v4 11 | with: 12 | node-version: 18 13 | cache: 'yarn' 14 | - run: yarn install --frozen-lockfile 15 | - run: yarn lint 16 | - run: yarn build -------------------------------------------------------------------------------- /ios/RNTuyaSdk/Utils/TuyaRNUtils+Network.h: -------------------------------------------------------------------------------- 1 | // 2 | // TuyaRNUtils+Network.h 3 | // TuyaRnDemo 4 | // 5 | // Created by 浩天 on 2019/3/2. 6 | // Copyright © 2019年 Facebook. All rights reserved. 7 | // 8 | 9 | #import "TuyaRNUtils.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface TuyaRNUtils (Network) 14 | 15 | + (void)openNetworkSettings; 16 | 17 | @end 18 | 19 | NS_ASSUME_NONNULL_END 20 | -------------------------------------------------------------------------------- /ios/RNTuyaSdk/Core/TuyaRNCoreModule.h: -------------------------------------------------------------------------------- 1 | // 2 | // TuyaCoreApi.h 3 | // TuyaSdkTest 4 | // 5 | // Created by 浩天 on 2019/2/27. 6 | // Copyright © 2019年 Facebook. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface TuyaRNCoreModule : NSObject 15 | 16 | @end 17 | 18 | NS_ASSUME_NONNULL_END 19 | -------------------------------------------------------------------------------- /ios/RNTuyaSdk/Home/TuyaRNHomeModule.h: -------------------------------------------------------------------------------- 1 | // 2 | // TuyaRNHomeModule.h 3 | // TuyaRnDemo 4 | // 5 | // Created by 浩天 on 2019/3/1. 6 | // Copyright © 2019年 Facebook. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface TuyaRNHomeModule : NSObject 15 | 16 | @end 17 | 18 | NS_ASSUME_NONNULL_END 19 | -------------------------------------------------------------------------------- /ios/RNTuyaSdk/User/TuyaRNUserModule.h: -------------------------------------------------------------------------------- 1 | // 2 | // TuyaRNUserModule.h 3 | // TuyaRnDemo 4 | // 5 | // Created by 浩天 on 2019/2/28. 6 | // Copyright © 2019年 Facebook. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface TuyaRNUserModule : NSObject 15 | 16 | @end 17 | 18 | NS_ASSUME_NONNULL_END 19 | -------------------------------------------------------------------------------- /ios/RNTuyaSdk/Group/TuyaRNGroupModule.h: -------------------------------------------------------------------------------- 1 | // 2 | // TuyaRNGroupModule.h 3 | // TuyaRnDemo 4 | // 5 | // Created by 浩天 on 2019/2/28. 6 | // Copyright © 2019年 Facebook. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface TuyaRNGroupModule : NSObject 15 | 16 | @end 17 | 18 | NS_ASSUME_NONNULL_END 19 | -------------------------------------------------------------------------------- /ios/RNTuyaSdk/Room/TuyaRNRoomModule.h: -------------------------------------------------------------------------------- 1 | // 2 | // TuyaRNRoomModule.h 3 | // TuyaRnDemo 4 | // 5 | // Created by 浩天 on 2019/2/28. 6 | // Copyright © 2019年 Facebook. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | 13 | NS_ASSUME_NONNULL_BEGIN 14 | 15 | @interface TuyaRNRoomModule : NSObject 16 | 17 | @end 18 | 19 | NS_ASSUME_NONNULL_END 20 | -------------------------------------------------------------------------------- /ios/RNTuyaSdk/Scene/TuyaRNSceneModule.h: -------------------------------------------------------------------------------- 1 | // 2 | // TuyaRNSceneModule.h 3 | // TuyaRnDemo 4 | // 5 | // Created by 浩天 on 2019/2/28. 6 | // Copyright © 2019年 Facebook. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface TuyaRNSceneModule : NSObject 15 | 16 | @end 17 | 18 | NS_ASSUME_NONNULL_END 19 | -------------------------------------------------------------------------------- /ios/RNTuyaSdk/Timer/TuyaRNTimerModule.h: -------------------------------------------------------------------------------- 1 | // 2 | // TuyaRNTimerModule.h 3 | // TuyaRnDemo 4 | // 5 | // Created by 浩天 on 2019/2/28. 6 | // Copyright © 2019年 Facebook. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface TuyaRNTimerModule : NSObject 15 | 16 | @end 17 | 18 | NS_ASSUME_NONNULL_END 19 | -------------------------------------------------------------------------------- /ios/RNTuyaSdk/GateWay/TuyaRNGatewayModule.h: -------------------------------------------------------------------------------- 1 | // 2 | // TuyaRNGatewayModule.h 3 | // TuyaRnDemo 4 | // 5 | // Created by 浩天 on 2019/2/28. 6 | // Copyright © 2019年 Facebook. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface TuyaRNGatewayModule : NSObject 15 | 16 | @end 17 | 18 | NS_ASSUME_NONNULL_END 19 | -------------------------------------------------------------------------------- /ios/RNTuyaSdk/ShareDevice/TuyaRNShareModule.h: -------------------------------------------------------------------------------- 1 | // 2 | // TuyaRNShareModule.h 3 | // TuyaRnDemo 4 | // 5 | // Created by 浩天 on 2019/2/28. 6 | // Copyright © 2019年 Facebook. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface TuyaRNShareModule : NSObject 15 | 16 | @end 17 | 18 | NS_ASSUME_NONNULL_END 19 | -------------------------------------------------------------------------------- /ios/RNTuyaSdk/DeviceControl/TuyaRNDeviceModule.h: -------------------------------------------------------------------------------- 1 | // 2 | // TuyaRNDeviceModule.h 3 | // TuyaRnDemo 4 | // 5 | // Created by 浩天 on 2019/2/28. 6 | // Copyright © 2019年 Facebook. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface TuyaRNDeviceModule : NSObject 15 | 16 | @end 17 | 18 | NS_ASSUME_NONNULL_END 19 | -------------------------------------------------------------------------------- /ios/RNTuyaSdk/Feedback/TuyaRNFeedBackModule.h: -------------------------------------------------------------------------------- 1 | // 2 | // TuyaRNFeedBackModule.h 3 | // TuyaRnDemo 4 | // 5 | // Created by 浩天 on 2019/2/28. 6 | // Copyright © 2019年 Facebook. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface TuyaRNFeedBackModule : NSObject 15 | 16 | @end 17 | 18 | NS_ASSUME_NONNULL_END 19 | -------------------------------------------------------------------------------- /ios/RNTuyaSdk/GateWay/TuyaRNGatewayModule.m: -------------------------------------------------------------------------------- 1 | // 2 | // TuyaRNGatewayModule.m 3 | // TuyaRnDemo 4 | // 5 | // Created by 浩天 on 2019/2/28. 6 | // Copyright © 2019年 Facebook. All rights reserved. 7 | // 8 | 9 | #import "TuyaRNGatewayModule.h" 10 | 11 | @implementation TuyaRNGatewayModule 12 | 13 | RCT_EXPORT_MODULE(TuyaGatewayModule) 14 | 15 | RCT_EXPORT_METHOD(initWithOptions:(NSDictionary *)params) { 16 | 17 | } 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /ios/RNTuyaSdk/Home/TuyaRNHomeMemberModule.h: -------------------------------------------------------------------------------- 1 | // 2 | // TuyaRNHomeMemberModule.h 3 | // TuyaRnDemo 4 | // 5 | // Created by 浩天 on 2019/3/1. 6 | // Copyright © 2019年 Facebook. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface TuyaRNHomeMemberModule : NSObject 15 | 16 | @end 17 | 18 | NS_ASSUME_NONNULL_END 19 | -------------------------------------------------------------------------------- /ios/RNTuyaSdk/Activator/TuyaRNActivatorModule.h: -------------------------------------------------------------------------------- 1 | // 2 | // TuyaRNActivatorModule.h 3 | // TuyaRnDemo 4 | // 5 | // Created by 浩天 on 2019/2/28. 6 | // Copyright © 2019年 Facebook. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface TuyaRNActivatorModule : NSObject 15 | 16 | @end 17 | 18 | NS_ASSUME_NONNULL_END 19 | -------------------------------------------------------------------------------- /ios/RNTuyaSdk/Home/TuyaRNHomeManagerModule.h: -------------------------------------------------------------------------------- 1 | // 2 | // TuyaRNHomeManagerModule.h 3 | // TuyaRnDemo 4 | // 5 | // Created by 浩天 on 2019/2/28. 6 | // Copyright © 2019年 Facebook. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface TuyaRNHomeManagerModule : NSObject 15 | 16 | @end 17 | 18 | NS_ASSUME_NONNULL_END 19 | -------------------------------------------------------------------------------- /ios/RNTuyaSdk/BLEScanner/TuyaBLERNScannerModule.h: -------------------------------------------------------------------------------- 1 | // 2 | // TuyaBLERNScannerModule.h 3 | // TuyaRnDemo 4 | // 5 | // Created by 浩天 on 2019/2/28. 6 | // Copyright © 2019年 Facebook. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface TuyaBLERNScannerModule : NSObject 15 | 16 | @end 17 | 18 | NS_ASSUME_NONNULL_END 19 | -------------------------------------------------------------------------------- /ios/RNTuyaSdk/MessageCenter/TuyaRNMessageModule.h: -------------------------------------------------------------------------------- 1 | // 2 | // TuyaRNMessageModule.h 3 | // TuyaRnDemo 4 | // 5 | // Created by 浩天 on 2019/2/28. 6 | // Copyright © 2019年 Facebook. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | 13 | NS_ASSUME_NONNULL_BEGIN 14 | 15 | @interface TuyaRNMessageModule : NSObject 16 | 17 | @end 18 | 19 | NS_ASSUME_NONNULL_END 20 | -------------------------------------------------------------------------------- /ios/RNTuyaSdk/Utils/TuyaRNUtils+Cache.h: -------------------------------------------------------------------------------- 1 | // 2 | // TuyaRNUtils+Cache.h 3 | // TuyaRnDemo 4 | // 5 | // Created by 浩天 on 2019/3/2. 6 | // Copyright © 2019年 Facebook. All rights reserved. 7 | // 8 | 9 | #import "TuyaRNUtils.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface TuyaRNUtils (Cache) 14 | 15 | + (NSNumber *)currentHomeId; 16 | 17 | + (void)setCurrentHomeId:(NSNumber *)homeId; 18 | 19 | @end 20 | 21 | NS_ASSUME_NONNULL_END 22 | -------------------------------------------------------------------------------- /ios/RNTuyaSdk/BLEActivator/TuyaBLERNActivatorModule.h: -------------------------------------------------------------------------------- 1 | // 2 | // TuyaBLERNActivatorModule.h 3 | // TuyaRnDemo 4 | // 5 | // Created by 浩天 on 2019/2/28. 6 | // Copyright © 2019年 Facebook. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface TuyaBLERNActivatorModule : NSObject 15 | 16 | @end 17 | 18 | NS_ASSUME_NONNULL_END 19 | -------------------------------------------------------------------------------- /ios/RNTuyaSdk/Home/TuyaRNHomeDataManagerModule.h: -------------------------------------------------------------------------------- 1 | // 2 | // TuyaRNHomeDataManagerModule.h 3 | // TuyaRnDemo 4 | // 5 | // Created by 浩天 on 2019/3/2. 6 | // Copyright © 2019年 Facebook. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface TuyaRNHomeDataManagerModule : NSObject 15 | 16 | @end 17 | 18 | NS_ASSUME_NONNULL_END 19 | -------------------------------------------------------------------------------- /src/homeDataManager.ts: -------------------------------------------------------------------------------- 1 | import { NativeModules } from 'react-native'; 2 | 3 | const tuya = NativeModules.TuyaHomeDataManagerModule; 4 | 5 | export type GetRoomDeviceListParams = { 6 | homeId?: number; 7 | roomId: number; 8 | }; 9 | 10 | export type GetRoomDeviceListResponse = { 11 | deviceList: {}[]; 12 | groupList: {}[]; 13 | }; 14 | 15 | export function getRoomDeviceList( 16 | params: GetRoomDeviceListParams 17 | ): Promise { 18 | return tuya.getRoomDeviceList(params); 19 | } 20 | -------------------------------------------------------------------------------- /android/src/main/java/com/tuya/smart/rnsdk/utils/ReactParamsCheck.kt: -------------------------------------------------------------------------------- 1 | package com.tuya.smart.rnsdk.utils 2 | 3 | import com.facebook.react.bridge.ReadableMap 4 | 5 | object ReactParamsCheck { 6 | /** 7 | * 接口输入参数check 8 | */ 9 | fun checkParams(keys: Array, params: ReadableMap): Boolean { 10 | for (key in keys) { 11 | if (!params.hasKey(key)) { 12 | throw IllegalArgumentException("need ${key}") 13 | } 14 | } 15 | return true 16 | } 17 | } -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | 8 | jobs: 9 | release: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - uses: actions/checkout@v4 13 | - uses: actions/setup-node@v4 14 | with: 15 | node-version: 18 16 | cache: 'yarn' 17 | - run: yarn install --frozen-lockfile 18 | - run: yarn build 19 | - env: 20 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 21 | NPM_TOKEN: ${{ secrets.NPM_TOKEN }} 22 | run: yarn semantic-release -------------------------------------------------------------------------------- /.releaserc.json: -------------------------------------------------------------------------------- 1 | { 2 | "branches": [ 3 | "master" 4 | ], 5 | "plugins": [ 6 | "@semantic-release/commit-analyzer", 7 | "@semantic-release/release-notes-generator", 8 | "@semantic-release/github", 9 | "@semantic-release/npm", 10 | [ 11 | "@semantic-release/git", 12 | { 13 | "assets": [ 14 | "docs", 15 | "package.json" 16 | ], 17 | "message": "chore(release): ${nextRelease.version} [skip ci]" 18 | } 19 | ] 20 | ], 21 | "tagFormat": "${version}" 22 | } -------------------------------------------------------------------------------- /ios/RNTuyaSdk/Utils/TuyaRNUtils.h: -------------------------------------------------------------------------------- 1 | // 2 | // TuyaRNUtils.h 3 | // TuyaRnDemo 4 | // 5 | // Created by 浩天 on 2019/2/28. 6 | // Copyright © 2019年 Facebook. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | 13 | NS_ASSUME_NONNULL_BEGIN 14 | 15 | @interface TuyaRNUtils : NSObject 16 | 17 | + (void)rejecterWithError:(NSError *)error 18 | handler:(RCTPromiseRejectBlock)rejecter; 19 | 20 | + (void)resolverWithHandler:(RCTPromiseResolveBlock)resolver; 21 | 22 | @end 23 | 24 | NS_ASSUME_NONNULL_END 25 | -------------------------------------------------------------------------------- /RNTuyaSdk.podspec: -------------------------------------------------------------------------------- 1 | require 'json' 2 | 3 | package = JSON.parse(File.read(File.join(__dir__, 'package.json'))) 4 | 5 | Pod::Spec.new do |s| 6 | s.name = "RNTuyaSdk" 7 | s.version = package['version'] 8 | s.summary = package['description'] 9 | s.license = package['license'] 10 | 11 | s.authors = package['author'] 12 | s.homepage = package['homepage'] 13 | s.platforms = { :ios => "12.0" } 14 | 15 | s.source = { :git => "https://github.com/owowagency/react-native-tuya.git", :tag => "v#{s.version}" } 16 | s.source_files = "ios/**/*.{h,m}" 17 | 18 | s.dependency 'React' 19 | s.dependency 'ThingSmartHomeKit', '~> 5.8.0' 20 | end 21 | -------------------------------------------------------------------------------- /ios/RNTuyaSdk/Utils/TuyaRNUtils.m: -------------------------------------------------------------------------------- 1 | // 2 | // TuyaRNUtils.m 3 | // TuyaRnDemo 4 | // 5 | // Created by 浩天 on 2019/2/28. 6 | // Copyright © 2019年 Facebook. All rights reserved. 7 | // 8 | 9 | #import "TuyaRNUtils.h" 10 | 11 | 12 | @implementation TuyaRNUtils 13 | 14 | + (void)rejecterWithError:(NSError *)error 15 | handler:(RCTPromiseRejectBlock)rejecter { 16 | if (rejecter) { 17 | rejecter([NSString stringWithFormat:@"%ld", error.code], error.userInfo[NSLocalizedDescriptionKey], error); 18 | } 19 | } 20 | 21 | + (void)resolverWithHandler:(RCTPromiseResolveBlock)resolver { 22 | if (resolver) { 23 | resolver(@"success"); 24 | } 25 | } 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /android/consumer-rules.pro: -------------------------------------------------------------------------------- 1 | # https://developer.tuya.com/en/docs/app-development/integrated?id=Ka69nt96cw0uj#title-7-Step%205%3A%20Obfuscate%20the%20code 2 | 3 | #fastJson 4 | -keep class com.alibaba.fastjson.**{*;} 5 | -dontwarn com.alibaba.fastjson.** 6 | 7 | #mqtt 8 | -keep class com.thingclips.smart.mqttclient.mqttv3.** { *; } 9 | -dontwarn com.thingclips.smart.mqttclient.mqttv3.** 10 | 11 | #OkHttp3 12 | -keep class okhttp3.** { *; } 13 | -keep interface okhttp3.** { *; } 14 | -dontwarn okhttp3.** 15 | 16 | -keep class okio.** { *; } 17 | -dontwarn okio.** 18 | 19 | -keep class com.thingclips.**{*;} 20 | -dontwarn com.thingclips.** 21 | 22 | # Matter SDK 23 | -keep class chip.** { *; } 24 | -dontwarn chip.** -------------------------------------------------------------------------------- /android/README.md: -------------------------------------------------------------------------------- 1 | # README 2 | 3 | If you want to publish the lib as a maven dependency, follow these steps before publishing a new version to npm: 4 | 5 | 1. Be sure to have the Android [SDK](https://developer.android.com/studio/index.html) and [NDK](https://developer.android.com/ndk/guides/index.html) installed 6 | 2. Be sure to have a `local.properties` file in this folder that points to the Android SDK and NDK 7 | 8 | ``` 9 | ndk.dir=/Users/{username}/Library/Android/sdk/ndk-bundle 10 | sdk.dir=/Users/{username}/Library/Android/sdk 11 | ``` 12 | 13 | 3. Delete the `maven` folder 14 | 4. Run `sudo ./gradlew installArchives` 15 | 5. Verify that latest set of generated files is in the maven folder with the correct version number 16 | -------------------------------------------------------------------------------- /ios/RNTuyaSdk/Utils/TuyaRNUtils+Cache.m: -------------------------------------------------------------------------------- 1 | // 2 | // TuyaRNUtils+Cache.m 3 | // TuyaRnDemo 4 | // 5 | // Created by 浩天 on 2019/3/2. 6 | // Copyright © 2019年 Facebook. All rights reserved. 7 | // 8 | 9 | #import "TuyaRNUtils+Cache.h" 10 | 11 | #define kTuyaRNSDKCurrentHomeId @"TuyaRNSDKCurrentHomeId" 12 | 13 | @implementation TuyaRNUtils (Cache) 14 | 15 | + (NSNumber *)currentHomeId { 16 | return [[NSUserDefaults standardUserDefaults] objectForKey:kTuyaRNSDKCurrentHomeId]; 17 | } 18 | 19 | + (void)setCurrentHomeId:(NSNumber *)homeId { 20 | if (!homeId) { 21 | return; 22 | } 23 | [[NSUserDefaults standardUserDefaults] setObject:homeId forKey:kTuyaRNSDKCurrentHomeId]; 24 | [[NSUserDefaults standardUserDefaults] synchronize]; 25 | } 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /src/bridgeUtils.ts: -------------------------------------------------------------------------------- 1 | import { NativeEventEmitter, NativeModules } from 'react-native'; 2 | 3 | export const GROUPLISTENER = 'groupListener'; 4 | export const HARDWAREUPGRADELISTENER = 'hardwareUpgradeListener'; 5 | export const DEVLISTENER = 'devListener'; 6 | export const SUBDEVLISTENER = 'subDevListener'; 7 | export const HOMESTATUS = 'homeStatus'; 8 | export const HOMECHANGE = 'homeChange'; 9 | export const SINGLETRANSFER = 'SingleTransfer'; 10 | 11 | let eventEmitter = new NativeEventEmitter(NativeModules.TuyaRNEventEmitter); 12 | 13 | export function addEvent(eventName: string, callback: (data: any) => any) { 14 | return eventEmitter.addListener(eventName, callback); 15 | } 16 | export const bridge = (key: string, id: string | number) => `${key}//${id}`; 17 | -------------------------------------------------------------------------------- /ios/RNTuyaSdk/Utils/Listener/TuyaRNEventEmitter.h: -------------------------------------------------------------------------------- 1 | // 2 | // TuyaRNEventEmitter.h 3 | // TuyaRnDemo 4 | // 5 | // Created by 浩天 on 2019/3/4. 6 | // Copyright © 2019年 Facebook. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | extern NSString *const kTYEventEmitterDeviceInfoEvent; 13 | //extern NSString *const kTYEventEmitterFirmwareUpdateEvent; 14 | extern NSString *const kTYEventEmitterGroupInfoEvent; 15 | extern NSString *const kTYEventEmitterHomeChangeEvent; 16 | extern NSString *const kTYEventEmitterHomeStatusEvent; 17 | 18 | NS_ASSUME_NONNULL_BEGIN 19 | 20 | @interface TuyaRNEventEmitter : RCTEventEmitter 21 | 22 | + (void)ty_sendEvent:(NSString *)event withBody:(id)body; 23 | 24 | @end 25 | 26 | NS_ASSUME_NONNULL_END 27 | -------------------------------------------------------------------------------- /ios/RNTuyaSdk/Utils/Listener/TuyaRNHomeManagerListener.h: -------------------------------------------------------------------------------- 1 | // 2 | // TuyaRNHomeManagerListener.h 3 | // TuyaRnDemo 4 | // 5 | // Created by 浩天 on 2019/3/6. 6 | // Copyright © 2019年 Facebook. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | #import 12 | #import 13 | 14 | 15 | 16 | 17 | NS_ASSUME_NONNULL_BEGIN 18 | 19 | @interface TuyaRNHomeManagerListener : NSObject 20 | 21 | /** 22 | 单例 23 | */ 24 | + (instancetype)sharedInstance; 25 | 26 | /** 27 | 注册家庭管理通知 28 | 29 | */ 30 | - (void)registerSmartHomeManager:(ThingSmartHomeManager *)homeManager; 31 | 32 | 33 | /** 34 | 移除家庭管理的通知 35 | */ 36 | - (void)removeSmartHomeManager; 37 | 38 | @end 39 | 40 | NS_ASSUME_NONNULL_END 41 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": ["src", "types", "test"], 3 | "compilerOptions": { 4 | "target": "es5", 5 | "module": "esnext", 6 | "lib": ["dom", "esnext"], 7 | "importHelpers": true, 8 | "declaration": true, 9 | "sourceMap": true, 10 | "rootDir": "./", 11 | "strict": true, 12 | "noImplicitAny": true, 13 | "strictNullChecks": true, 14 | "strictFunctionTypes": true, 15 | "strictPropertyInitialization": true, 16 | "noImplicitThis": true, 17 | "alwaysStrict": true, 18 | "noUnusedLocals": true, 19 | "noUnusedParameters": true, 20 | "noImplicitReturns": true, 21 | "noFallthroughCasesInSwitch": true, 22 | "moduleResolution": "node", 23 | "baseUrl": "./", 24 | "paths": { 25 | "*": ["src/*", "node_modules/*"] 26 | }, 27 | "jsx": "react", 28 | "esModuleInterop": true 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /ios/RNTuyaSdk/Utils/Listener/TuyaRNHomeListener.h: -------------------------------------------------------------------------------- 1 | // 2 | // TuyaRNHomeListener.h 3 | // TuyaRnDemo 4 | // 5 | // Created by 浩天 on 2019/3/6. 6 | // Copyright © 2019年 Facebook. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | #import 12 | #import 13 | 14 | 15 | NS_ASSUME_NONNULL_BEGIN 16 | 17 | @interface TuyaRNHomeListener : NSObject 18 | 19 | + (instancetype)shareInstance; 20 | 21 | //注册新的SmartHome 22 | - (void)registerHomeChangeWithSmartHome:(ThingSmartHome *)smartHome; 23 | 24 | //取消注册 25 | - (void)removeHomeChangeSmartHome; 26 | 27 | //注册新的 监听status 28 | - (void)registerHomeStatusWithSmartHome:(ThingSmartHome *)smartHome; 29 | 30 | //取消 监听 31 | - (void)removeHomeStatusSmartHome; 32 | 33 | @end 34 | 35 | NS_ASSUME_NONNULL_END 36 | -------------------------------------------------------------------------------- /src/ota.ts: -------------------------------------------------------------------------------- 1 | import { NativeModules } from 'react-native'; 2 | import { addEvent, bridge, HARDWAREUPGRADELISTENER } from './bridgeUtils'; 3 | 4 | const tuya = NativeModules.TuyaDeviceModule; 5 | 6 | export type StartOtaParams = { 7 | devId: string; 8 | }; 9 | 10 | export function startOta( 11 | params: StartOtaParams, 12 | onSuccess: (data: any) => void, 13 | onFailure: (data: any) => void, 14 | onProgress: (data: any) => void 15 | ) { 16 | tuya.startOta(params); 17 | return addEvent(bridge(HARDWAREUPGRADELISTENER, params.devId), data => { 18 | if (data.type === 'onSuccess') { 19 | onSuccess(data); 20 | } else if (data.type === 'onFailure') { 21 | onFailure(data); 22 | } else if (data.type === 'onProgress') { 23 | onProgress(data); 24 | } 25 | }); 26 | } 27 | 28 | export function getOtaInfo(params: StartOtaParams): Promise { 29 | return tuya.getOtaInfo(params); 30 | } 31 | -------------------------------------------------------------------------------- /ios/RNTuyaSdk/Utils/Listener/TuyaRNDeviceListener.h: -------------------------------------------------------------------------------- 1 | // 2 | // TuyaRNDeviceListener.h 3 | // TuyaRnDemo 4 | // 5 | // Created by 浩天 on 2019/3/4. 6 | // Copyright © 2019年 Facebook. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class ThingSmartDevice; 12 | 13 | typedef NS_OPTIONS(NSUInteger, TuyaRNDeviceListenType) { 14 | TuyaRNDeviceListenType_None = 1<<0, 15 | TuyaRNDeviceListenType_DeviceInfo = 1 << 1, 16 | }; 17 | 18 | NS_ASSUME_NONNULL_BEGIN 19 | 20 | @interface TuyaRNDeviceListener : NSObject 21 | 22 | @property (nonatomic, copy, readonly) NSArray *listenDevices; 23 | 24 | + (instancetype)shareInstance; 25 | 26 | /** 27 | 添加设备监听, 当设备状态变更时,会自动发送 kTYEventEmitterDeviceListenerEvent 28 | */ 29 | + (void)registerDevice:(ThingSmartDevice *)device type:(TuyaRNDeviceListenType)type; 30 | 31 | /* 32 | * 移除设备监听 33 | */ 34 | + (void)removeDevice:(ThingSmartDevice *)device type:(TuyaRNDeviceListenType)type; 35 | 36 | 37 | @end 38 | 39 | NS_ASSUME_NONNULL_END 40 | -------------------------------------------------------------------------------- /ios/RNTuyaSdk/Utils/TuyaRNUtils+Network.m: -------------------------------------------------------------------------------- 1 | // 2 | // TuyaRNUtils+Network.m 3 | // TuyaRnDemo 4 | // 5 | // Created by 浩天 on 2019/3/2. 6 | // Copyright © 2019年 Facebook. All rights reserved. 7 | // 8 | 9 | #import "TuyaRNUtils+Network.h" 10 | #import 11 | 12 | @implementation TuyaRNUtils (Network) 13 | 14 | + (void)openNetworkSettings { 15 | 16 | NSData *data = [[NSData alloc] initWithBase64EncodedString:@"QXBwLVByZWZzJTNBcm9vdCUzRFdJRkk=" options:0]; 17 | NSString *urlStr = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; 18 | urlStr = [urlStr stringByRemovingPercentEncoding]; 19 | NSURL *targetUrl = [NSURL URLWithString:urlStr]; 20 | if (targetUrl && [[UIApplication sharedApplication] canOpenURL:targetUrl]) { 21 | if (@available(iOS 10.0, *)) { 22 | [[UIApplication sharedApplication] openURL:targetUrl options:@{} completionHandler:nil]; 23 | } else { 24 | [[UIApplication sharedApplication] openURL:targetUrl]; 25 | } 26 | } 27 | } 28 | 29 | @end 30 | -------------------------------------------------------------------------------- /android/src/main/java/com/tuya/smart/rnsdk/push/TuyaPushModule.kt: -------------------------------------------------------------------------------- 1 | package com.tuya.smart.rnsdk.push 2 | 3 | import com.facebook.react.bridge.* 4 | import com.thingclips.smart.home.sdk.ThingHomeSdk 5 | import com.tuya.smart.rnsdk.utils.Constant 6 | import com.tuya.smart.rnsdk.utils.ReactParamsCheck 7 | 8 | class TuyaPushModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) { 9 | override fun getName(): String { 10 | return "TuyaPushModule" 11 | } 12 | 13 | /* Push涂鸦云注册 */ 14 | @ReactMethod 15 | fun registerDevice(params: ReadableMap, promise: Promise) { 16 | if (ReactParamsCheck.checkParams(arrayOf(Constant.ALIASID, Constant.PUSHPROVIDER), params)) { 17 | ThingHomeSdk.getPushInstance().registerDevice(params.getString(Constant.ALIASID),params.getString(Constant.PUSHPROVIDER),Constant.getIResultCallback(promise)) 18 | } 19 | } 20 | 21 | 22 | /* 手机密码登录 */ 23 | @ReactMethod 24 | fun onDestroy() { 25 | ThingHomeSdk.getPushInstance().onDestroy() 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Volst 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /android/src/main/java/com/tuya/smart/rnsdk/utils/JsonUtils.kt: -------------------------------------------------------------------------------- 1 | package com.tuya.smart.rnsdk.utils 2 | 3 | import com.alibaba.fastjson.JSON 4 | import com.alibaba.fastjson.JSONArray 5 | import com.alibaba.fastjson.JSONObject 6 | import com.facebook.react.bridge.ReadableArray 7 | import com.facebook.react.bridge.ReadableMap 8 | 9 | object JsonUtils { 10 | fun parse(json: String, c: Class<*>): Any { 11 | return JSONObject.parseObject(json, c) 12 | } 13 | 14 | 15 | fun parseArray(json: String, c: Class<*>): List { 16 | return JSONObject.parseArray(json, c) 17 | } 18 | 19 | fun parserArraybyMap(map: ReadableArray, c: Class<*>): List? { 20 | return parseArray(toString(TuyaReactUtils.parseToList(map)), c) 21 | } 22 | 23 | fun parseBymap(map: ReadableMap, c: Class<*>): Any? { 24 | return parse(JSONObject(TuyaReactUtils.parseToMap(map)).toJSONString(), c) 25 | } 26 | fun toString(obj:Any):String{ 27 | return JSONObject.toJSONString(obj) 28 | } 29 | fun toJsonArray(obj:Any):JSONArray{ 30 | return JSONArray.parseArray(JSON.toJSONString(obj)) 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | dist/ 3 | */build/ 4 | 5 | node_modules/ 6 | 7 | # OSX 8 | # 9 | .DS_Store 10 | 11 | # Xcode 12 | # 13 | *.pbxuser 14 | !default.pbxuser 15 | *.mode1v3 16 | !default.mode1v3 17 | *.mode2v3 18 | !default.mode2v3 19 | *.perspectivev3 20 | !default.perspectivev3 21 | xcuserdata 22 | *.xccheckout 23 | *.moved-aside 24 | DerivedData 25 | *.hmap 26 | *.ipa 27 | *.xcuserstate 28 | 29 | # Android/IntelliJ 30 | # 31 | build/ 32 | .idea 33 | .gradle 34 | .settings 35 | .project 36 | local.properties 37 | *.iml 38 | .classpath 39 | gradlew* 40 | gradle 41 | 42 | 43 | 44 | # node.js 45 | # 46 | npm-debug.log 47 | yarn-error.log 48 | 49 | # BUCK 50 | buck-out/ 51 | \.buckd/ 52 | *.keystore 53 | 54 | # fastlane 55 | # 56 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 57 | # screenshots whenever they are needed. 58 | # For more information about the recommended setup visit: 59 | # https://docs.fastlane.tools/best-practices/source-control/ 60 | 61 | */fastlane/report.xml 62 | */fastlane/Preview.html 63 | */fastlane/screenshots 64 | 65 | # Bundle artifact 66 | *.jsbundle 67 | *.zip 68 | *.lock 69 | !yarn.lock 70 | !package-lock.json 71 | -------------------------------------------------------------------------------- /src/homeManager.ts: -------------------------------------------------------------------------------- 1 | import { NativeModules, Platform } from 'react-native'; 2 | 3 | const tuya = NativeModules.TuyaHomeManagerModule; 4 | 5 | export type CreateHomeParams = { 6 | name: string; 7 | geoName: string; 8 | lon: number; 9 | lat: number; 10 | rooms: string[]; 11 | }; 12 | 13 | export function createHome(params: CreateHomeParams): Promise { 14 | return tuya.createHome(params); 15 | } 16 | 17 | export type HomeDetailsResponse = { 18 | name: string; 19 | admin: boolean; 20 | background: string; 21 | dealStatus: 1 | 2; // 1 = unaccepted 2 = accepted 22 | displayOrder: number; 23 | geoName: string; 24 | gid: number; 25 | homeId: number; 26 | lat: number; 27 | lon: number; 28 | }; 29 | 30 | export type QueryHomeListResponse = HomeDetailsResponse[]; 31 | 32 | export async function queryHomeList(): Promise { 33 | let homes = await tuya.queryHomeList(); 34 | // Tuya's Android SDK uses different property names than the iOS SDK... 35 | if (Platform.OS === 'android') { 36 | homes = homes.map((m: any) => ({ 37 | ...m, 38 | dealStatus: m.homeStatus, 39 | })); 40 | } 41 | return homes; 42 | } 43 | 44 | export type JoinFamilyParams = { 45 | homeId: number; 46 | action: boolean; 47 | }; 48 | 49 | export function joinFamily(params: JoinFamilyParams) { 50 | return tuya.joinFamily(params); 51 | } 52 | -------------------------------------------------------------------------------- /src/homeMember.ts: -------------------------------------------------------------------------------- 1 | import { NativeModules, Platform } from 'react-native'; 2 | 3 | const tuya = NativeModules.TuyaHomeMemberModule; 4 | 5 | export type QueryMemberListParams = { homeId: number }; 6 | export type MemberListItem = { 7 | admin: boolean; 8 | username: string; 9 | id: number; 10 | dealStatus: number; 11 | }; 12 | export type QueryMemberListResponse = MemberListItem[]; 13 | 14 | export async function queryMemberList( 15 | params: QueryMemberListParams 16 | ): Promise { 17 | let members = await tuya.queryMemberList(params); 18 | // Tuya's Android SDK uses different property names than the iOS SDK... 19 | if (Platform.OS === 'android') { 20 | members = members.map((m: any) => ({ 21 | admin: m.admin, 22 | username: m.account, 23 | id: m.memberId, 24 | dealStatus: m.memberStatus, 25 | })); 26 | } 27 | return members; 28 | } 29 | 30 | export type AddMemberParams = { 31 | homeId: number; 32 | userAccount: string; // email 33 | countryCode: string; 34 | name: string; 35 | admin: boolean; 36 | }; 37 | 38 | export function addMember(params: AddMemberParams): Promise { 39 | return tuya.addMember(params); 40 | } 41 | 42 | export type RemoveMemberParams = { 43 | memberId: number; 44 | }; 45 | 46 | export function removeMember(params: RemoveMemberParams): Promise { 47 | return tuya.removeMember(params); 48 | } 49 | -------------------------------------------------------------------------------- /ios/RNTuyaSdk/Utils/TuyaRNUtils+DeviceParser.h: -------------------------------------------------------------------------------- 1 | // 2 | // TuyaRNUtils+DeviceParser.h 3 | // TuyaRnDemo 4 | // 5 | // Created by 浩天 on 2019/3/4. 6 | // Copyright © 2019年 Facebook. All rights reserved. 7 | // 8 | 9 | #import "TuyaRNUtils.h" 10 | #import 11 | #import 12 | #import 13 | 14 | static inline NSArray *getValidDataForDeviceModel(NSArray *deviceModelList) { 15 | if(!deviceModelList || [deviceModelList count] == 0) { 16 | return @[]; 17 | } 18 | NSMutableArray *list = [NSMutableArray array]; 19 | for (ThingSmartDeviceModel *tempModel in deviceModelList) { 20 | 21 | NSDictionary *dic = [tempModel yy_modelToJSONObject]; 22 | [list addObject:dic]; 23 | } 24 | return list; 25 | } 26 | 27 | static inline NSArray *getValidDataForGroupModel(NSArray *groupModelList) { 28 | if(!groupModelList || [groupModelList count] == 0) { 29 | return @[]; 30 | } 31 | 32 | NSMutableArray *list = [NSMutableArray array]; 33 | for (ThingSmartGroupModel *tempModel in groupModelList) { 34 | NSDictionary *dic = [tempModel yy_modelToJSONObject]; 35 | [list addObject:dic]; 36 | } 37 | return list; 38 | } 39 | 40 | 41 | NS_ASSUME_NONNULL_BEGIN 42 | 43 | @interface TuyaRNUtils (DeviceParser) 44 | 45 | @end 46 | 47 | NS_ASSUME_NONNULL_END 48 | -------------------------------------------------------------------------------- /android/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | 23 | # https://developer.tuya.com/en/docs/app-development/integrated?id=Ka69nt96cw0uj#title-7-Step%205%3A%20Obfuscate%20the%20code 24 | 25 | #fastJson 26 | -keep class com.alibaba.fastjson.**{*;} 27 | -dontwarn com.alibaba.fastjson.** 28 | 29 | #mqtt 30 | -keep class com.thingclips.smart.mqttclient.mqttv3.** { *; } 31 | -dontwarn com.thingclips.smart.mqttclient.mqttv3.** 32 | 33 | #OkHttp3 34 | -keep class okhttp3.** { *; } 35 | -keep interface okhttp3.** { *; } 36 | -dontwarn okhttp3.** 37 | 38 | -keep class okio.** { *; } 39 | -dontwarn okio.** 40 | 41 | -keep class com.thingclips.**{*;} 42 | -dontwarn com.thingclips.** 43 | 44 | # Matter SDK 45 | -keep class chip.** { *; } 46 | -dontwarn chip.** -------------------------------------------------------------------------------- /ios/RNTuyaSdk/BLEScanner/TuyaBLERNScannerModule.m: -------------------------------------------------------------------------------- 1 | // 2 | // TuyaBLERNScannerModule.m 3 | // TuyaRnDemo 4 | // 5 | // Created by 浩天 on 2019/2/28. 6 | // Copyright © 2019年 Facebook. All rights reserved. 7 | // 8 | 9 | #import "TuyaBLERNScannerModule.h" 10 | #import 11 | #import 12 | #import 13 | #import 14 | #import "TuyaRNUtils+Network.h" 15 | #import "YYModel.h" 16 | 17 | // Bluetooth Pairing 18 | static TuyaBLERNScannerModule * scannerInstance = nil; 19 | 20 | @interface TuyaBLERNScannerModule() 21 | 22 | @property(copy, nonatomic) RCTPromiseResolveBlock promiseResolveBlock; 23 | @property(copy, nonatomic) RCTPromiseRejectBlock promiseRejectBlock; 24 | 25 | @end 26 | 27 | @implementation TuyaBLERNScannerModule 28 | 29 | RCT_EXPORT_MODULE(TuyaBLEScannerModule) 30 | 31 | RCT_EXPORT_METHOD(startBluetoothScan:(RCTPromiseResolveBlock)resolver rejecter:(RCTPromiseRejectBlock)rejecter) { 32 | if (scannerInstance == nil) { 33 | scannerInstance = [TuyaBLERNScannerModule new]; 34 | } 35 | 36 | [ThingSmartBLEManager sharedInstance].delegate = scannerInstance; 37 | scannerInstance.promiseResolveBlock = resolver; 38 | scannerInstance.promiseRejectBlock = rejecter; 39 | 40 | [[ThingSmartBLEManager sharedInstance] startListening:YES]; 41 | } 42 | 43 | - (void)didDiscoveryDeviceWithDeviceInfo:(ThingBLEAdvModel *)deviceInfo { 44 | if (scannerInstance.promiseResolveBlock) { 45 | self.promiseResolveBlock([deviceInfo yy_modelToJSONObject]); 46 | } 47 | } 48 | 49 | @end 50 | -------------------------------------------------------------------------------- /src/activator.ts: -------------------------------------------------------------------------------- 1 | import { DeviceBean } from './device'; 2 | import { NativeModules, Platform } from 'react-native'; 3 | import { DeviceDetailResponse } from './home'; 4 | 5 | const tuya = NativeModules.TuyaActivatorModule; 6 | const tuyaBLEActivator = NativeModules.TuyaBLEActivatorModule; 7 | const tuyaBLEScanner = NativeModules.TuyaBLEScannerModule; 8 | 9 | export function openNetworkSettings() { 10 | return tuya.openNetworkSettings({}); 11 | } 12 | 13 | export enum ActivatorType { 14 | AP = 'THING_AP', 15 | EZ = 'THING_EZ', 16 | AP_4G_GATEWAY = 'THING_4G_GATEWAY', 17 | QR = 'THING_QR', 18 | } 19 | 20 | export type InitActivatorParams = { 21 | homeId: number; 22 | ssid: string; 23 | password: string; 24 | time: number; 25 | type: ActivatorType; 26 | }; 27 | 28 | export interface InitBluetoothActivatorParams { 29 | deviceId?: string; 30 | homeId: number; 31 | ssid: string; 32 | password: string; 33 | } 34 | 35 | export function initActivator( 36 | params: InitActivatorParams 37 | ): Promise { 38 | return tuya.initActivator(params); 39 | } 40 | 41 | export function stopConfig() { 42 | return tuya.stopConfig(); 43 | } 44 | 45 | export function startBluetoothScan() { 46 | if (Platform.OS === 'ios') { 47 | return tuyaBLEScanner.startBluetoothScan(); 48 | } 49 | return tuya.startBluetoothScan(); 50 | } 51 | 52 | export function initBluetoothDualModeActivator( 53 | params: InitBluetoothActivatorParams 54 | ): Promise { 55 | if (Platform.OS === 'ios') { 56 | return tuyaBLEActivator.initActivator(params); 57 | } 58 | return tuya.initBluetoothDualModeActivator(params); 59 | } 60 | 61 | export function getCurrentWifi( 62 | success: (ssid: string) => void, 63 | error: () => void 64 | ) { 65 | // We need the Allow While Using App location permission to use this. 66 | return tuya.getCurrentWifi({}, success, error); 67 | } 68 | -------------------------------------------------------------------------------- /src/home.ts: -------------------------------------------------------------------------------- 1 | import { NativeModules } from 'react-native'; 2 | import { DeviceDps } from './device'; 3 | 4 | const tuya = NativeModules.TuyaHomeModule; 5 | 6 | export type QueryRoomListParams = { 7 | homeId?: number; 8 | }; 9 | export type QueryRoomListResponse = { 10 | name: string; 11 | displayOrder: number; 12 | id: number; 13 | roomId: number; 14 | }[]; 15 | 16 | export function queryRoomList( 17 | params: QueryRoomListParams 18 | ): Promise { 19 | return tuya.queryRoomList(params); 20 | } 21 | 22 | export type GetHomeDetailParams = { 23 | homeId: number; 24 | }; 25 | export type DeviceDetailResponse = { 26 | homeId: number; 27 | isOnline: boolean; 28 | productId: string; 29 | devId: string; 30 | verSw: string; 31 | name: string; 32 | dps: DeviceDps; 33 | homeDisplayOrder: number; 34 | roomId: number; 35 | }; 36 | export type GetHomeDetailResponse = { 37 | deviceList: DeviceDetailResponse[]; 38 | groupList: any[]; 39 | meshList: any[]; 40 | sharedDeviceList: any[]; 41 | sharedGroupList: any[]; 42 | }; 43 | 44 | export function getHomeDetail( 45 | params: GetHomeDetailParams 46 | ): Promise { 47 | return tuya.getHomeDetail(params); 48 | } 49 | 50 | export type UpdateHomeParams = { 51 | homeId: number; 52 | name: string; 53 | geoName: string; 54 | lon: number; 55 | lat: number; 56 | }; 57 | 58 | export function updateHome(params: UpdateHomeParams): Promise { 59 | return tuya.updateHome(params); 60 | } 61 | 62 | export type DismissHomeParams = { 63 | homeId: number; 64 | }; 65 | 66 | export function dismissHome(params: DismissHomeParams): Promise { 67 | return tuya.dismissHome(params); 68 | } 69 | 70 | export type SortRoomsParams = { 71 | idList: number[]; 72 | homeId: number; 73 | }; 74 | 75 | export function sortRoom(params: SortRoomsParams): Promise { 76 | return tuya.sortRoom(params); 77 | } 78 | -------------------------------------------------------------------------------- /android/src/main/java/com/tuya/smart/rnsdk/utils/BridgeUtils.kt: -------------------------------------------------------------------------------- 1 | package com.tuya.smart.rnsdk.utils 2 | 3 | import android.util.Log 4 | import com.facebook.react.bridge.ReactContext 5 | import com.facebook.react.bridge.WritableMap 6 | 7 | object BridgeUtils { 8 | 9 | private val GROUPLISTENER = "groupListener" 10 | private val HARDWAREUPGRADELISTENER = "hardwareUpgradeListener" 11 | private val DEVLISTENER = "devListener" 12 | private val SUBDEVLISTENER = "subDevListener" 13 | private val HOMESTATUS = "homeStatus" 14 | private val HOMECHANGE = "homeChange" 15 | private val SINGLETRANSFER = "SingleTransfer" 16 | 17 | fun groupListener(context: ReactContext, map: WritableMap, groupId: Long) { 18 | TuyaReactUtils.sendEvent(context, bindEventname(GROUPLISTENER, groupId), map) 19 | } 20 | 21 | fun hardwareUpgradeListener(context: ReactContext, map: WritableMap, devId: String){ 22 | TuyaReactUtils.sendEvent(context, bindEventname(HARDWAREUPGRADELISTENER, devId), map) 23 | } 24 | fun devListener(context: ReactContext, map: WritableMap, devId: String){ 25 | TuyaReactUtils.sendEvent(context, bindEventname(DEVLISTENER, devId), map) 26 | } 27 | fun subDevListener(context: ReactContext, map: WritableMap, devId: String){ 28 | TuyaReactUtils.sendEvent(context, bindEventname(SUBDEVLISTENER, devId), map) 29 | } 30 | fun singleTransferListener(context: ReactContext, map: WritableMap, devId: String){ 31 | TuyaReactUtils.sendEvent(context, bindEventname(SINGLETRANSFER, devId), map) 32 | } 33 | fun homeStatus(context: ReactContext, map: WritableMap, devId: String){ 34 | TuyaReactUtils.sendEvent(context, bindEventname(HOMESTATUS, devId), map) 35 | } 36 | 37 | fun homeChange(context: ReactContext, map: WritableMap, homeId: Double){ 38 | TuyaReactUtils.sendEvent(context, HOMECHANGE, map) 39 | } 40 | 41 | private fun bindEventname(key: String, id: Any): String { 42 | return key + "//" + id.toString() 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.0.0-RC.2", 3 | "license": "MIT", 4 | "private": false, 5 | "main": "dist/index.js", 6 | "typings": "dist/index.d.ts", 7 | "keywords": [ 8 | "react-native", 9 | "tuyasmart", 10 | "iot", 11 | "tuya" 12 | ], 13 | "files": [ 14 | "android", 15 | "ios", 16 | "dist", 17 | "RNTuyaSdk.podspec" 18 | ], 19 | "scripts": { 20 | "start": "tsdx watch", 21 | "build": "tsdx build", 22 | "test": "tsdx test", 23 | "lint": "tsdx lint", 24 | "commit": "cz", 25 | "prepare": "husky install" 26 | }, 27 | "peerDependencies": { 28 | "react-native": ">=0.61.5" 29 | }, 30 | "husky": { 31 | "hooks": { 32 | "pre-commit": "tsdx lint" 33 | } 34 | }, 35 | "prettier": { 36 | "singleQuote": true, 37 | "trailingComma": "es5" 38 | }, 39 | "name": "@owowagency/react-native-tuya", 40 | "description": "React Native bindings for the Tuya SDK", 41 | "homepage": "https://github.com/owowagency/react-native-tuya#readme", 42 | "author": "Kees Kluskens", 43 | "module": "dist/react-native-tuya.esm.js", 44 | "devDependencies": { 45 | "@types/jest": "^25.1.2", 46 | "@types/react-native": "^0.61.16", 47 | "@volst/eslint-config": "^4.1.1", 48 | "react-native": "^0.61.5", 49 | "tsdx": "^0.12.3", 50 | "tslib": "^1.10.0", 51 | "typescript": "^3.7.5", 52 | "@commitlint/cli": "^18.1.0", 53 | "@commitlint/config-conventional": "^18.1.0", 54 | "@semantic-release/commit-analyzer": "^11.0.0", 55 | "@semantic-release/exec": "^6.0.3", 56 | "@semantic-release/git": "^10.0.1", 57 | "@semantic-release/npm": "^11.0.0", 58 | "commitizen": "^4.3.0", 59 | "commitlint": "^18.1.0", 60 | "conventional-changelog-conventionalcommits": "^7.0.2", 61 | "cz-conventional-changelog": "^3.3.0", 62 | "husky": "^8.0.3", 63 | "semantic-release": "^22.0.5" 64 | }, 65 | "config": { 66 | "commitizen": { 67 | "path": "./node_modules/cz-conventional-changelog" 68 | } 69 | }, 70 | "publishConfig": { 71 | "access": "public", 72 | "registry": "https://registry.npmjs.org/" 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/user.ts: -------------------------------------------------------------------------------- 1 | import { NativeModules } from 'react-native'; 2 | 3 | const tuya = NativeModules.TuyaUserModule; 4 | 5 | export function registerAccountWithEmail( 6 | params: RegisterAccountWithEmailParams 7 | ): Promise { 8 | return tuya.registerAccountWithEmail(params); 9 | } 10 | 11 | export function getRegisterEmailValidateCode( 12 | params: GetEmailValidateCodeParams 13 | ): Promise { 14 | return tuya.getRegisterEmailValidateCode(params); 15 | } 16 | 17 | export function loginWithEmail(params: LoginWithEmailParams): Promise { 18 | return tuya.loginWithEmail(params); 19 | } 20 | 21 | export function getEmailValidateCode( 22 | params: GetEmailValidateCodeParams 23 | ): Promise { 24 | return tuya.getEmailValidateCode(params); 25 | } 26 | 27 | export function resetEmailPassword( 28 | params: ResetEmailPasswordParams 29 | ): Promise { 30 | return tuya.resetEmailPassword(params); 31 | } 32 | 33 | export function logout(): Promise { 34 | return tuya.logout(); 35 | } 36 | 37 | export async function getCurrentUser(): Promise { 38 | const user = await tuya.getCurrentUser(); 39 | // The iOS SDK returns an empty user model but the Android one doesn't. 40 | return user && user.email ? user : null; 41 | } 42 | 43 | export function cancelAccount(): Promise { 44 | return tuya.cancelAccount(); 45 | } 46 | 47 | export type User = { 48 | email: string; 49 | username: string; 50 | sid: string; 51 | timezoneId: string; 52 | uid: string; 53 | userType: number; 54 | headPic: string; 55 | mobile: string; 56 | nickName: string; 57 | phoneCode: string; 58 | }; 59 | 60 | export type RegisterAccountWithEmailParams = { 61 | countryCode: string; 62 | email: string; 63 | validateCode: string; 64 | password: string; 65 | }; 66 | 67 | export type GetEmailValidateCodeParams = { 68 | countryCode: string; 69 | email: string; 70 | }; 71 | 72 | export type LoginWithEmailParams = { 73 | email: string; 74 | password: string; 75 | countryCode: string; 76 | }; 77 | 78 | export type ResetEmailPasswordParams = { 79 | email: string; 80 | countryCode: string; 81 | validateCode: string; 82 | newPassword: string; 83 | }; 84 | -------------------------------------------------------------------------------- /ios/RNTuyaSdk/Utils/Listener/TuyaRNEventEmitter.m: -------------------------------------------------------------------------------- 1 | // 2 | // TuyaRNEventEmitter.m 3 | // TuyaRnDemo 4 | // 5 | // Created by 浩天 on 2019/3/4. 6 | // Copyright © 2019年 Facebook. All rights reserved. 7 | // 8 | 9 | #import "TuyaRNEventEmitter.h" 10 | 11 | NSString *const kTYEventEmitterDeviceInfoEvent = @"devListener"; 12 | //NSString *const kTYEventEmitterFirmwareUpdateEvent = @"hardwareUpgradeListener"; 13 | NSString *const kTYEventEmitterGroupInfoEvent = @"groupListener"; 14 | NSString *const kTYEventEmitterHomeChangeEvent = @"homeChange"; 15 | NSString *const kTYEventEmitterHomeStatusEvent = @"homeStatus"; 16 | 17 | 18 | 19 | @interface TuyaRNEventEmitter() 20 | 21 | @property (nonatomic) BOOL hasListeners; 22 | 23 | @property (nonatomic, strong) NSMutableArray *supportedEvents; 24 | 25 | @end 26 | 27 | @implementation TuyaRNEventEmitter 28 | 29 | 30 | RCT_EXPORT_MODULE() 31 | 32 | - (NSArray *)supportedEvents { 33 | return _supportedEvents; 34 | } 35 | 36 | - (void)addListener:(NSString *)eventName { 37 | [_supportedEvents addObject:eventName]; 38 | [[NSNotificationCenter defaultCenter] addObserver:self 39 | selector:@selector(deviceInfoNotification:) 40 | name:eventName 41 | object:nil]; 42 | [super addListener:eventName]; 43 | } 44 | 45 | - (void)startObserving { 46 | 47 | } 48 | 49 | - (void)stopObserving { 50 | [[NSNotificationCenter defaultCenter] removeObserver:self]; 51 | } 52 | 53 | #pragma mark - Native 54 | - (instancetype)init { 55 | if (self = [super init]) { 56 | _supportedEvents = [NSMutableArray array]; 57 | } 58 | return self; 59 | } 60 | 61 | + (BOOL)requiresMainQueueSetup { 62 | return YES; 63 | } 64 | 65 | - (void)deviceInfoNotification:(NSNotification *)notification { 66 | NSDictionary *body = notification.object; 67 | [self sendEventWithName:notification.name body:body]; 68 | } 69 | 70 | + (void)ty_sendEvent:(NSString *)event withBody:(id)body { 71 | [[NSNotificationCenter defaultCenter] postNotificationName:event object:body]; 72 | // [[TuyaRNEventEmitter sharedInstance] sendEventWithName:event body:body]; 73 | } 74 | 75 | @end 76 | -------------------------------------------------------------------------------- /src/device.ts: -------------------------------------------------------------------------------- 1 | import { NativeModules, EmitterSubscription } from 'react-native'; 2 | import { addEvent, bridge, DEVLISTENER } from './bridgeUtils'; 3 | 4 | const tuya = NativeModules.TuyaDeviceModule; 5 | 6 | export type DeviceBean = { 7 | productId: string; 8 | devId: string; 9 | verSw: string; 10 | name: string; 11 | dps: DeviceDps; 12 | }; 13 | 14 | export type DevListenerParams = { 15 | devId: string; 16 | }; 17 | 18 | export type DevListenerType = 19 | | 'onDpUpdate' 20 | | 'onRemoved' 21 | | 'onStatusChanged' 22 | | 'onNetworkStatusChanged' 23 | | 'onDevInfoUpdate' 24 | | 'onFirmwareUpgradeSuccess' 25 | | 'onFirmwareUpgradeFailure' 26 | | 'onFirmwareUpgradeProgress'; 27 | 28 | let devListenerSubs: { [devId: string]: EmitterSubscription } = {}; 29 | 30 | export function registerDevListener( 31 | params: DevListenerParams, 32 | type: DevListenerType, 33 | callback: (data: any) => void 34 | ) { 35 | tuya.registerDevListener(params); 36 | const sub = addEvent(bridge(DEVLISTENER, params.devId), data => { 37 | if (data.type === type) { 38 | callback(data); 39 | } 40 | }); 41 | devListenerSubs[params.devId] = sub; 42 | } 43 | 44 | export function unRegisterAllDevListeners() { 45 | for (const devId in devListenerSubs) { 46 | const sub = devListenerSubs[devId]; 47 | sub.remove(); 48 | tuya.unRegisterDevListener({ devId }); 49 | } 50 | devListenerSubs = {}; 51 | } 52 | 53 | export type DeviceDpValue = boolean | number | string; 54 | export type DeviceDps = { 55 | [dpId: string]: DeviceDpValue; 56 | }; 57 | export type SendParams = { 58 | devId: string; 59 | } & DeviceDps; 60 | 61 | export function send(params: object) { 62 | return tuya.send(params); 63 | } 64 | 65 | export type RemoveDeviceParams = { devId: string }; 66 | 67 | export function removeDevice(params: RemoveDeviceParams): Promise { 68 | return tuya.removeDevice(params); 69 | } 70 | 71 | export type RenameDeviceParams = { devId: string; name: string }; 72 | 73 | export function renameDevice(params: RenameDeviceParams): Promise { 74 | return tuya.renameDevice(params); 75 | } 76 | 77 | export type GetDataPointStatsParams = { 78 | devId: string; 79 | DataPointTypeEnum: 'DAY' | 'WEEK' | 'MONTH'; 80 | number: number; // number of historical data result values, up to 50 81 | dpId: string; 82 | startTime: number; // in ms 83 | }; 84 | 85 | export function getDataPointStat( 86 | params: GetDataPointStatsParams 87 | ): Promise { 88 | return tuya.getDataPointStat(params); 89 | } 90 | -------------------------------------------------------------------------------- /src/timer.ts: -------------------------------------------------------------------------------- 1 | import { NativeModules } from 'react-native'; 2 | import { DeviceDps } from './device'; 3 | 4 | const tuya = NativeModules.TuyaTimerModule; 5 | 6 | export type AddTimerWithTaskDpsParams = { 7 | devId: number; 8 | taskName: string; 9 | loops: string; // Number of cycles "0000000", each 0: off, 1: on, from left to right: Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday 10 | time: string; // e.g. 14:29 11 | dps: DeviceDps; 12 | }; 13 | 14 | export function addTimerWithTask( 15 | params: AddTimerWithTaskDpsParams 16 | ): Promise { 17 | return tuya.addTimerWithTask(params); 18 | } 19 | 20 | export type UpdateTimerWithTaskParams = AddTimerWithTaskDpsParams & { 21 | timerId: string; 22 | isOpen: boolean; 23 | }; 24 | 25 | export function updateTimerWithTask( 26 | params: UpdateTimerWithTaskParams 27 | ): Promise { 28 | return tuya.updateTimerWithTask(params); 29 | } 30 | 31 | export type GetTimerTaskStatusWithDeviceIdParams = { 32 | devId: number; 33 | }; 34 | 35 | export function getTimerTaskStatusWithDeviceId( 36 | params: GetTimerTaskStatusWithDeviceIdParams 37 | ): Promise { 38 | return tuya.getTimerTaskStatusWithDeviceId(params); 39 | } 40 | 41 | export type GetAllTimerWithDeviceIdParams = { 42 | devId: number; 43 | }; 44 | 45 | export type TimerTask = { 46 | timerList: { 47 | timerId: string; 48 | loops: string; 49 | time: string; 50 | status: number; 51 | }[]; 52 | timerTaskStatus: { open: boolean; timerName: string }; 53 | }; 54 | 55 | export type GetAllTimerWithDeviceIdResponse = TimerTask[]; 56 | 57 | export async function getAllTimerWithDeviceId( 58 | params: GetAllTimerWithDeviceIdParams 59 | ): Promise { 60 | const timers = await tuya.getAllTimerWithDeviceId(params); 61 | timers.forEach((t: any) => { 62 | t.timerTaskStatus.open = !!t.timerTaskStatus.open; 63 | }); 64 | return timers; 65 | } 66 | 67 | export type RemoveTimerWithTaskParams = { 68 | devId: number; 69 | taskName: string; 70 | timerId: string; 71 | }; 72 | 73 | export function removeTimerWithTask( 74 | params: RemoveTimerWithTaskParams 75 | ): Promise { 76 | return tuya.removeTimerWithTask(params); 77 | } 78 | 79 | export type UpdateTimerStatusWithTaskParams = { 80 | devId: number; 81 | taskName: string; 82 | timerId: string; 83 | isOpen: boolean; 84 | }; 85 | 86 | export function updateTimerStatusWithTask( 87 | params: UpdateTimerStatusWithTaskParams 88 | ): Promise { 89 | return tuya.updateTimerStatusWithTask(params); 90 | } 91 | -------------------------------------------------------------------------------- /ios/RNTuyaSdk/MessageCenter/TuyaRNMessageModule.m: -------------------------------------------------------------------------------- 1 | // 2 | // TuyaRNMessageModule.m 3 | // TuyaRnDemo 4 | // 5 | // Created by 浩天 on 2019/2/28. 6 | // Copyright © 2019年 Facebook. All rights reserved. 7 | // 8 | 9 | #import "TuyaRNMessageModule.h" 10 | #import "TuyaRNUtils.h" 11 | #import 12 | #import 13 | 14 | 15 | @interface TuyaRNMessageModule() 16 | @property (nonatomic, strong) ThingSmartMessage *smartMessage; 17 | @end 18 | 19 | 20 | @implementation TuyaRNMessageModule 21 | 22 | RCT_EXPORT_MODULE(TuyaMessageModule) 23 | 24 | RCT_EXPORT_METHOD(initWithOptions:(NSDictionary *)params) { 25 | 26 | } 27 | 28 | RCT_EXPORT_METHOD(onDestory:(NSDictionary *)params) { 29 | 30 | } 31 | 32 | 33 | // 获取消息列表: 34 | RCT_EXPORT_METHOD(getMessageList:(RCTPromiseResolveBlock)resolver rejecter:(RCTPromiseRejectBlock)rejecter) { 35 | ThingSmartMessage *smartMessage = [[ThingSmartMessage alloc] init]; 36 | self.smartMessage = smartMessage; 37 | [smartMessage getMessageList:^(NSArray *list) { 38 | NSMutableArray *res = [NSMutableArray array]; 39 | for (ThingSmartMessageListModel *item in list) { 40 | NSDictionary *dic = [item yy_modelToJSONObject]; 41 | [res addObject:dic]; 42 | } 43 | if (resolver) { 44 | resolver(res); 45 | } 46 | } failure:^(NSError *error) { 47 | [TuyaRNUtils rejecterWithError:error handler:rejecter]; 48 | }]; 49 | } 50 | 51 | 52 | // 删除消息: 53 | RCT_EXPORT_METHOD(deleteMessage:(NSDictionary *)params resolver:(RCTPromiseResolveBlock)resolver rejecter:(RCTPromiseRejectBlock)rejecter) { 54 | ThingSmartMessage *smartMessage = [[ThingSmartMessage alloc] init]; 55 | self.smartMessage = smartMessage; 56 | [smartMessage deleteMessage:params[@"ids"] success:^{ 57 | if (resolver) { 58 | resolver(@"seccess"); 59 | } 60 | } failure:^(NSError *error) { 61 | [TuyaRNUtils rejecterWithError:error handler:rejecter]; 62 | }]; 63 | } 64 | 65 | // 获取最新的时间戳: 66 | RCT_EXPORT_METHOD(getMessageMaxTime:(RCTPromiseResolveBlock)resolver rejecter:(RCTPromiseRejectBlock)rejecter) { 67 | ThingSmartMessage *smartMessage = [[ThingSmartMessage alloc] init]; 68 | self.smartMessage = smartMessage; 69 | [smartMessage getMessageMaxTime:^(int result) { 70 | if (resolver) { 71 | resolver(@(result)); 72 | } 73 | } failure:^(NSError *error) { 74 | [TuyaRNUtils rejecterWithError:error handler:rejecter]; 75 | }]; 76 | } 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | @end 90 | -------------------------------------------------------------------------------- /ios/RNTuyaSdk/Utils/Listener/TuyaRNHomeManagerListener.m: -------------------------------------------------------------------------------- 1 | // 2 | // TuyaRNHomeManagerListener.m 3 | // TuyaRnDemo 4 | // 5 | // Created by 浩天 on 2019/3/6. 6 | // Copyright © 2019年 Facebook. All rights reserved. 7 | // 8 | 9 | #import "TuyaRNHomeManagerListener.h" 10 | #import "TuyaRNEventEmitter.h" 11 | 12 | @interface TuyaRNHomeManagerListener() 13 | 14 | @property (nonatomic, strong) ThingSmartHomeManager *currentSmartHomeManager; 15 | 16 | @end 17 | 18 | @implementation TuyaRNHomeManagerListener 19 | 20 | + (instancetype)sharedInstance { 21 | static TuyaRNHomeManagerListener *_instanced = nil; 22 | static dispatch_once_t onceToken; 23 | dispatch_once(&onceToken, ^{ 24 | _instanced = [[TuyaRNHomeManagerListener alloc] init]; 25 | }); 26 | return _instanced; 27 | } 28 | 29 | //注册家庭管理监听: 30 | - (void)registerSmartHomeManager:(ThingSmartHomeManager *)homeManager { 31 | if (!homeManager) { 32 | return; 33 | } 34 | [TuyaRNHomeManagerListener sharedInstance].currentSmartHomeManager = homeManager; 35 | homeManager.delegate = self; 36 | } 37 | 38 | - (void)removeSmartHomeManager { 39 | [TuyaRNHomeManagerListener sharedInstance].currentSmartHomeManager = nil; 40 | [TuyaRNHomeManagerListener sharedInstance].currentSmartHomeManager.delegate = nil; 41 | } 42 | 43 | #pragma mark - 44 | #pragma mark - ThingSmartHomeManagerDelegate 45 | // 添加一个家庭 46 | - (void)homeManager:(ThingSmartHomeManager *)manager didAddHome:(ThingSmartHomeModel *)home { 47 | 48 | long long homeId = home.homeId; 49 | if (!(homeId > 0)) { 50 | return; 51 | } 52 | NSDictionary *dic = @{ 53 | @"homeId": [NSNumber numberWithLongLong:homeId], 54 | @"type": @"onHomeAdded" 55 | }; 56 | [TuyaRNEventEmitter ty_sendEvent:[kTYEventEmitterHomeChangeEvent stringByAppendingString:@"//"] withBody:dic]; 57 | } 58 | 59 | // 删除一个家庭 60 | - (void)homeManager:(ThingSmartHomeManager *)manager didRemoveHome:(long long)homeId { 61 | 62 | if (!(homeId > 0)) { 63 | return; 64 | } 65 | NSDictionary *dic = @{ 66 | @"homeId": [NSNumber numberWithLongLong:homeId], 67 | @"type": @"onHomeRemoved" 68 | }; 69 | [TuyaRNEventEmitter ty_sendEvent:[kTYEventEmitterHomeChangeEvent stringByAppendingString:@"//"] withBody:dic]; 70 | 71 | } 72 | 73 | // MQTT连接成功 74 | - (void)serviceConnectedSuccess { 75 | // NSDictionary *dic = @{@"type": @"onServerConnectSuccess"}; 76 | // [TuyaRNEventEmitter ty_sendEvent:kTYEventEmitterHomeChangeEvent withBody:dic]; 77 | } 78 | 79 | @end 80 | -------------------------------------------------------------------------------- /android/src/main/java/com/tuya/smart/rnsdk/home/TuyaRoomModule.kt: -------------------------------------------------------------------------------- 1 | package com.tuya.smart.rnsdk.home 2 | 3 | import com.facebook.react.bridge.* 4 | import com.thingclips.smart.home.sdk.ThingHomeSdk 5 | import com.thingclips.smart.home.sdk.api.IThingRoom 6 | import com.tuya.smart.rnsdk.utils.Constant.NAME 7 | import com.tuya.smart.rnsdk.utils.Constant.DEVID 8 | import com.tuya.smart.rnsdk.utils.Constant.GROUPID 9 | import com.tuya.smart.rnsdk.utils.Constant.ROOMID 10 | import com.tuya.smart.rnsdk.utils.Constant.getIResultCallback 11 | import com.tuya.smart.rnsdk.utils.ReactParamsCheck 12 | 13 | 14 | class TuyaRoomModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) { 15 | override fun getName(): String { 16 | return "TuyaRoomModule" 17 | } 18 | 19 | /* 更新房间名称 */ 20 | @ReactMethod 21 | fun updateRoom(params: ReadableMap, promise: Promise) { 22 | if (ReactParamsCheck.checkParams(arrayOf(ROOMID, NAME), params)) { 23 | getRoomInstance(params.getDouble(ROOMID)).updateRoom(params.getString(NAME), getIResultCallback(promise)) 24 | } 25 | } 26 | 27 | /* 添加设备 */ 28 | @ReactMethod 29 | fun addDevice(params: ReadableMap, promise: Promise) { 30 | if (ReactParamsCheck.checkParams(arrayOf(ROOMID, DEVID), params)) { 31 | getRoomInstance(params.getDouble(ROOMID)).addDevice(params.getString(DEVID), getIResultCallback(promise)) 32 | } 33 | } 34 | 35 | /* 删除设备 */ 36 | @ReactMethod 37 | fun removeDevice(params: ReadableMap, promise: Promise) { 38 | if (ReactParamsCheck.checkParams(arrayOf(ROOMID, DEVID), params)) { 39 | getRoomInstance(params.getDouble(ROOMID)).removeDevice(params.getString(DEVID), getIResultCallback(promise)) 40 | } 41 | } 42 | 43 | /* 删除群组 */ 44 | @ReactMethod 45 | fun removeGroup(params: ReadableMap, promise: Promise) { 46 | if (ReactParamsCheck.checkParams(arrayOf(ROOMID, GROUPID), params)) { 47 | getRoomInstance(params.getDouble(ROOMID)).removeGroup(params.getDouble(GROUPID).toLong(), getIResultCallback(promise)) 48 | } 49 | } 50 | 51 | /* 添加群组 */ 52 | @ReactMethod 53 | fun addGroup(params: ReadableMap, promise: Promise) { 54 | if (ReactParamsCheck.checkParams(arrayOf(ROOMID, GROUPID), params)) { 55 | getRoomInstance(params.getDouble(ROOMID)).addGroup(params.getDouble(GROUPID).toLong(), getIResultCallback(promise)) 56 | } 57 | } 58 | 59 | fun getRoomInstance(roomId: Double): IThingRoom { 60 | return ThingHomeSdk.newRoomInstance(roomId.toLong()) 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /android/src/main/java/com/tuya/smart/rnsdk/message/TuyaMessageModule.kt: -------------------------------------------------------------------------------- 1 | package com.tuya.smart.rnsdk.message 2 | 3 | import com.facebook.react.bridge.* 4 | import com.thingclips.smart.android.user.api.IBooleanCallback 5 | import com.thingclips.smart.home.sdk.ThingHomeSdk 6 | import com.thingclips.smart.sdk.api.IThingDataCallback 7 | import com.thingclips.smart.sdk.bean.message.MessageBean 8 | import com.tuya.smart.rnsdk.utils.Constant 9 | import com.tuya.smart.rnsdk.utils.Constant.IDS 10 | import com.tuya.smart.rnsdk.utils.JsonUtils 11 | import com.tuya.smart.rnsdk.utils.ReactParamsCheck 12 | import com.tuya.smart.rnsdk.utils.TuyaReactUtils 13 | import java.util.ArrayList 14 | 15 | 16 | 17 | class TuyaMessageModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) { 18 | override fun getName(): String { 19 | return "TuyaMessageModule" 20 | } 21 | @ReactMethod 22 | fun getMessageList(promise: Promise) { 23 | ThingHomeSdk.getMessageInstance().getMessageList(object : IThingDataCallback> { 24 | override fun onSuccess(p0: List?) { 25 | promise.resolve(TuyaReactUtils.parseToWritableArray(JsonUtils.toJsonArray(p0!!))) 26 | } 27 | 28 | override fun onError(p0: String?, p1: String?) { 29 | promise.reject(p0,p1) 30 | } 31 | }) 32 | } 33 | 34 | @ReactMethod 35 | fun deleteMessage(params: ReadableMap, promise: Promise) { 36 | if (ReactParamsCheck.checkParams(arrayOf(IDS), params)) { 37 | var list = ArrayList() 38 | var length = (params.getArray(Constant.IDS) as ReadableArray).size()-1 39 | for (index in 0..length) { 40 | list.add((params.getArray(Constant.IDS) as ReadableArray).getString(index) as String) 41 | } 42 | ThingHomeSdk.getMessageInstance().deleteMessages(list,object : IBooleanCallback { 43 | override fun onSuccess(){ 44 | promise.resolve(Constant.SUCCESS) 45 | } 46 | 47 | override fun onError(var1: String, var2: String) { 48 | promise.reject(var1,var2) 49 | } 50 | }) 51 | } 52 | } 53 | 54 | @ReactMethod 55 | fun getMessageMaxTime(promise: Promise){ 56 | ThingHomeSdk.getMessageInstance().getMessageMaxTime(object : IThingDataCallback { 57 | override fun onSuccess(p0: Int) { 58 | promise.resolve(p0) 59 | } 60 | 61 | override fun onError(p0: String?, p1: String?) { 62 | promise.reject(p0,p1) 63 | } 64 | }) 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /android/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | apply plugin: 'kotlin-android' 3 | apply plugin: 'maven-publish' 4 | 5 | 6 | buildscript { 7 | ext.kotlin_version = '1.7.20' 8 | repositories { 9 | jcenter() 10 | google() 11 | } 12 | 13 | dependencies { 14 | classpath 'com.android.tools.build:gradle:7.0.0' 15 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 16 | } 17 | } 18 | 19 | 20 | android { 21 | compileSdkVersion 31 22 | 23 | defaultConfig { 24 | minSdkVersion 23 25 | targetSdkVersion 25 26 | versionCode 1 27 | versionName "1.0" 28 | 29 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 30 | 31 | ndk { 32 | abiFilters "armeabi-v7a","arm64-v8a" 33 | } 34 | } 35 | 36 | packagingOptions { 37 | pickFirst 'lib/*/libc++_shared.so' 38 | } 39 | 40 | buildTypes { 41 | release { 42 | minifyEnabled false 43 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 44 | } 45 | } 46 | 47 | compileOptions { 48 | sourceCompatibility JavaVersion.VERSION_1_8 49 | targetCompatibility JavaVersion.VERSION_1_8 50 | } 51 | } 52 | 53 | configurations.all { 54 | exclude group: "com.thingclips.smart", module: 'thingsmart-modularCampAnno' 55 | } 56 | 57 | dependencies { 58 | implementation fileTree(dir: 'libs', include: ['*.jar']) 59 | implementation 'com.alibaba:fastjson:1.1.67.android' 60 | implementation 'com.squareup.okhttp3:okhttp-urlconnection:3.6.0' 61 | implementation 'org.eclipse.paho:org.eclipse.paho.client.mqttv3:1.2.0' 62 | implementation 'com.thingclips.smart:thingsmart:5.11.3' 63 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 64 | implementation 'com.facebook.react:react-native:+' 65 | implementation 'de.greenrobot:eventbus:2.4.0' 66 | implementation 'io.reactivex.rxjava2:rxandroid:2.0.1' 67 | implementation 'io.reactivex.rxjava2:rxjava:2.1.7' 68 | implementation 'org.eclipse.paho:org.eclipse.paho.android.service:1.1.1' 69 | implementation 'androidx.localbroadcastmanager:localbroadcastmanager:1.0.0' 70 | } 71 | 72 | repositories { 73 | mavenCentral() 74 | google() 75 | maven { url 'https://maven-other.tuya.com/repository/maven-releases/' } 76 | maven { url "https://maven-other.tuya.com/repository/maven-commercial-releases/" } 77 | maven { url 'https://maven.aliyun.com/repository/public' } 78 | maven { url 'https://oss.sonatype.org/content/repositories/snapshots/' } 79 | maven { url 'https://developer.huawei.com/repo/' } 80 | maven { url 'https://jitpack.io' } 81 | } 82 | 83 | allprojects { 84 | repositories { 85 | exclusiveContent { 86 | filter { 87 | includeGroup "com.facebook.react" 88 | } 89 | forRepository { 90 | maven { 91 | url "$rootDir/../node_modules/react-native/android" 92 | } 93 | } 94 | } 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /ios/RNTuyaSdk/BLEActivator/TuyaBLERNActivatorModule.m: -------------------------------------------------------------------------------- 1 | // 2 | // TuyaBLERNActivatorModule.m 3 | // TuyaRnDemo 4 | // 5 | // Created by 浩天 on 2019/2/28. 6 | // Copyright © 2019年 Facebook. All rights reserved. 7 | // 8 | 9 | #import "TuyaBLERNActivatorModule.h" 10 | #import 11 | #import 12 | #import 13 | #import 14 | #import 15 | #import "TuyaRNUtils+Network.h" 16 | #import "YYModel.h" 17 | 18 | #define kTuyaRNActivatorModuleHomeId @"homeId" 19 | #define kTuyaRNActivatorModuleDeviceId @"deviceId" 20 | #define kTuyaRNActivatorModuleProductId @"productId" 21 | #define kTuyaRNActivatorModuleSSID @"ssid" 22 | #define kTuyaRNActivatorModulePassword @"password" 23 | 24 | // Bluetooth Pairing 25 | static TuyaBLERNActivatorModule * activatorInstance = nil; 26 | 27 | @interface TuyaBLERNActivatorModule() 28 | 29 | @property(copy, nonatomic) RCTPromiseResolveBlock promiseResolveBlock; 30 | @property(copy, nonatomic) RCTPromiseRejectBlock promiseRejectBlock; 31 | 32 | @end 33 | 34 | @implementation TuyaBLERNActivatorModule 35 | 36 | RCT_EXPORT_MODULE(TuyaBLEActivatorModule) 37 | 38 | RCT_EXPORT_METHOD(initActivator:(NSDictionary *)params resolver:(RCTPromiseResolveBlock)resolver rejecter:(RCTPromiseRejectBlock)rejecter) { 39 | if (activatorInstance == nil) { 40 | activatorInstance = [TuyaBLERNActivatorModule new]; 41 | } 42 | 43 | [ThingSmartBLEWifiActivator sharedInstance].bleWifiDelegate = activatorInstance; 44 | activatorInstance.promiseResolveBlock = resolver; 45 | activatorInstance.promiseRejectBlock = rejecter; 46 | 47 | NSNumber *homeId = params[kTuyaRNActivatorModuleHomeId]; 48 | NSString *deviceId = params[kTuyaRNActivatorModuleDeviceId]; 49 | NSString *productId = params[kTuyaRNActivatorModuleProductId]; 50 | NSString *ssid = params[kTuyaRNActivatorModuleSSID]; 51 | NSString *password = params[kTuyaRNActivatorModulePassword]; 52 | long long int homeIdValue = [homeId longLongValue]; 53 | 54 | [[ThingSmartBLEWifiActivator sharedInstance] startConfigBLEWifiDeviceWithUUID:deviceId homeId:homeIdValue productId:productId ssid:ssid password:password timeout:180 success:^{ 55 | // Wait for activation 56 | } failure:^ { 57 | if (activatorInstance.promiseRejectBlock) { 58 | [TuyaRNUtils rejecterWithError:nil handler:rejecter]; 59 | } 60 | return; 61 | }]; 62 | } 63 | 64 | - (void)bleWifiActivator:(ThingSmartBLEWifiActivator *)activator didReceiveBLEWifiConfigDevice:(ThingSmartDeviceModel *)deviceModel error:(NSError *)error { 65 | if (!error && deviceModel) { 66 | if (activatorInstance.promiseResolveBlock) { 67 | self.promiseResolveBlock([deviceModel yy_modelToJSONObject]); 68 | } 69 | } 70 | if (error) { 71 | if (activatorInstance.promiseRejectBlock) { 72 | [TuyaRNUtils rejecterWithError:error handler:activatorInstance.promiseRejectBlock]; 73 | } 74 | } 75 | 76 | } 77 | 78 | @end 79 | -------------------------------------------------------------------------------- /android/src/main/java/com/tuya/smart/rnsdk/TuyaReactPackage.kt: -------------------------------------------------------------------------------- 1 | package com.tuya.smart.rnsdk 2 | 3 | 4 | import com.facebook.react.ReactPackage 5 | import com.facebook.react.bridge.JavaScriptModule 6 | import com.facebook.react.bridge.NativeModule 7 | import com.facebook.react.bridge.ReactApplicationContext 8 | import com.facebook.react.uimanager.ViewManager 9 | import com.tuya.smart.rnsdk.activator.TuyaActivatorModule 10 | import com.tuya.smart.rnsdk.core.TuyaCoreModule 11 | import com.tuya.smart.rnsdk.device.TuyaDeviceModule 12 | import com.tuya.smart.rnsdk.device.TuyaGatewayModule 13 | import com.tuya.smart.rnsdk.device.TuyaOTAModule 14 | import com.tuya.smart.rnsdk.device.TuyaSingleTransferModule 15 | import com.tuya.smart.rnsdk.feedback.TuyaFeedBackModule 16 | import com.tuya.smart.rnsdk.group.TuyaGroupModule 17 | import com.tuya.smart.rnsdk.home.TuyaHomeDataManagerModule 18 | import com.tuya.smart.rnsdk.home.TuyaHomeManagerModule 19 | import com.tuya.smart.rnsdk.home.TuyaHomeMemberModule 20 | import com.tuya.smart.rnsdk.home.TuyaHomeModule 21 | import com.tuya.smart.rnsdk.home.TuyaRoomModule 22 | import com.tuya.smart.rnsdk.message.TuyaMessageModule 23 | import com.tuya.smart.rnsdk.push.TuyaPushModule 24 | import com.tuya.smart.rnsdk.scene.TuyaSceneModule 25 | import com.tuya.smart.rnsdk.share.TuyaShareModule 26 | import com.tuya.smart.rnsdk.timer.TuyaTimerModule 27 | import com.tuya.smart.rnsdk.user.TuyaUserModule 28 | 29 | import java.util.* 30 | 31 | class TuyaReactPackage : ReactPackage { 32 | 33 | // override fun createJSModules(): MutableList> { 34 | // return Collections.emptyList(); 35 | // } 36 | 37 | override fun createNativeModules(reactContext: ReactApplicationContext): MutableList { 38 | val module: ArrayList = ArrayList() 39 | module.add(TuyaActivatorModule(reactContext)) 40 | module.add(TuyaCoreModule(reactContext)) 41 | module.add(TuyaDeviceModule(reactContext)) 42 | module.add(TuyaGatewayModule(reactContext)) 43 | module.add(TuyaOTAModule(reactContext)) 44 | module.add(TuyaSingleTransferModule(reactContext)) 45 | module.add(TuyaFeedBackModule(reactContext)) 46 | module.add(TuyaGroupModule(reactContext)) 47 | module.add(TuyaHomeDataManagerModule(reactContext)) 48 | module.add(TuyaHomeManagerModule(reactContext)) 49 | module.add(TuyaHomeMemberModule(reactContext)) 50 | module.add(TuyaHomeModule(reactContext)) 51 | module.add(TuyaRoomModule(reactContext)) 52 | module.add(TuyaMessageModule(reactContext)) 53 | module.add(TuyaPushModule(reactContext)) 54 | module.add(TuyaShareModule(reactContext)) 55 | module.add(TuyaTimerModule(reactContext)) 56 | module.add(TuyaUserModule(reactContext)) 57 | module.add(TuyaSceneModule(reactContext)) 58 | return module 59 | } 60 | 61 | override fun createViewManagers(reactContext: ReactApplicationContext): List> { 62 | val managers = ArrayList>() 63 | return managers 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /ios/RNTuyaSdk/Room/TuyaRNRoomModule.m: -------------------------------------------------------------------------------- 1 | // 2 | // TuyaRNRoomModule.m 3 | // TuyaRnDemo 4 | // 5 | // Created by 浩天 on 2019/2/28. 6 | // Copyright © 2019年 Facebook. All rights reserved. 7 | // 8 | 9 | #import "TuyaRNRoomModule.h" 10 | #import 11 | #import "TuyaRNUtils.h" 12 | 13 | #define kTuyaRNRoomModuleName @"name" 14 | #define kTuyaRNRoomModuleGroupId @"groupId" 15 | #define kTuyaRNRoomModuleDevId @"devId" 16 | #define kTuyaRNRoomModuleRoomId @"roomId" 17 | #define kTuyaRNRoomModuleHomeId @"homeId" 18 | 19 | @interface TuyaRNRoomModule() 20 | 21 | @property (strong, nonatomic) ThingSmartRoom *smartRoom; 22 | 23 | @end 24 | 25 | @implementation TuyaRNRoomModule 26 | 27 | RCT_EXPORT_MODULE(TuyaRoomModule) 28 | 29 | /** 30 | * 更新房间名称 31 | * 32 | * @param name 新房间名称 33 | */ 34 | RCT_EXPORT_METHOD(updateRoom:(NSDictionary *)params resolver:(RCTPromiseResolveBlock)resolver rejecter:(RCTPromiseRejectBlock)rejecter) { 35 | 36 | self.smartRoom = [self smartRoomWithParams:params]; 37 | NSString *name = params[kTuyaRNRoomModuleName]; 38 | 39 | [self.smartRoom updateRoomName:name success:^{ 40 | [TuyaRNUtils resolverWithHandler:resolver]; 41 | } failure:^(NSError *error) { 42 | [TuyaRNUtils rejecterWithError:error handler:rejecter]; 43 | }]; 44 | 45 | } 46 | 47 | RCT_EXPORT_METHOD(addDevice:(NSDictionary *)params resolver:(RCTPromiseResolveBlock)resolver rejecter:(RCTPromiseRejectBlock)rejecter) { 48 | 49 | self.smartRoom = [self smartRoomWithParams:params]; 50 | NSString *deviceId = params[kTuyaRNRoomModuleDevId]; 51 | 52 | [self.smartRoom addDeviceWithDeviceId:deviceId success:^{ 53 | [TuyaRNUtils resolverWithHandler:resolver]; 54 | } failure:^(NSError *error) { 55 | [TuyaRNUtils rejecterWithError:error handler:rejecter]; 56 | }]; 57 | } 58 | 59 | 60 | RCT_EXPORT_METHOD(removeDevice:(NSDictionary *)params resolver:(RCTPromiseResolveBlock)resolver rejecter:(RCTPromiseRejectBlock)rejecter) { 61 | 62 | self.smartRoom = [self smartRoomWithParams:params]; 63 | 64 | NSString *deviceId = params[kTuyaRNRoomModuleDevId]; 65 | 66 | [self.smartRoom removeDeviceWithDeviceId:deviceId success:^{ 67 | [TuyaRNUtils resolverWithHandler:resolver]; 68 | } failure:^(NSError *error) { 69 | [TuyaRNUtils rejecterWithError:error handler:rejecter]; 70 | }]; 71 | 72 | } 73 | 74 | RCT_EXPORT_METHOD(removeGroup:(NSDictionary *)params resolver:(RCTPromiseResolveBlock)resolver rejecter:(RCTPromiseRejectBlock)rejecter) { 75 | 76 | self.smartRoom = [self smartRoomWithParams:params]; 77 | 78 | NSString *groupId = params[kTuyaRNRoomModuleGroupId]; 79 | 80 | [self.smartRoom removeGroupWithGroupId:groupId success:^{ 81 | [TuyaRNUtils resolverWithHandler:resolver]; 82 | } failure:^(NSError *error) { 83 | [TuyaRNUtils rejecterWithError:error handler:rejecter]; 84 | }]; 85 | 86 | } 87 | 88 | #pragma mark - 89 | #pragma mark - init 90 | - (ThingSmartRoom *)smartRoomWithParams:(NSDictionary *)params { 91 | 92 | NSNumber *homeId = params[kTuyaRNRoomModuleHomeId]; 93 | NSNumber *roomId = params[kTuyaRNRoomModuleRoomId]; 94 | return [ThingSmartRoom roomWithRoomId:roomId.longLongValue homeId:homeId.longLongValue]; 95 | } 96 | 97 | @end 98 | -------------------------------------------------------------------------------- /android/src/main/java/com/tuya/smart/rnsdk/device/TuyaSingleTransferModule.kt: -------------------------------------------------------------------------------- 1 | package com.tuya.smart.rnsdk.device 2 | 3 | import com.facebook.react.bridge.* 4 | import com.thingclips.smart.home.sdk.ThingHomeSdk 5 | import com.thingclips.smart.home.sdk.bean.TransferDataBean 6 | import com.thingclips.smart.sdk.api.IThingDataCallback 7 | import com.tuya.smart.rnsdk.utils.BridgeUtils 8 | import com.tuya.smart.rnsdk.utils.Constant 9 | import com.tuya.smart.rnsdk.utils.Constant.DEVID 10 | import com.tuya.smart.rnsdk.utils.ReactParamsCheck 11 | import com.tuya.smart.rnsdk.utils.TuyaReactUtils 12 | 13 | class TuyaSingleTransferModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) { 14 | override fun getName(): String { 15 | return "TuyaSingleTransferModule" 16 | } 17 | 18 | /** 19 | * 开始连接 20 | */ 21 | @ReactMethod 22 | fun startConnect() { 23 | ThingHomeSdk.getTransferInstance().startConnect() 24 | } 25 | 26 | /** 27 | * 是否在线 28 | */ 29 | @ReactMethod 30 | fun isOnline(promise: Promise) { 31 | promise.resolve(ThingHomeSdk.getTransferInstance().isOnline) 32 | } 33 | 34 | /** 35 | * 订阅设备数据,订阅设备之后,设备如果有数据上报上来,便可以通过 registerTransferDataListener 回调上来。需要注意的是,每次通道连接成功都需要重新订阅设备数据 36 | */ 37 | @ReactMethod 38 | fun subscribeDevice(params: ReadableMap) { 39 | if (ReactParamsCheck.checkParams(arrayOf(Constant.DEVID), params)) { 40 | ThingHomeSdk.getTransferInstance().subscribeDevice(params.getString(DEVID)) 41 | } 42 | } 43 | 44 | /** 45 | * 取消订阅设备信息,则设备数据不在收到 46 | * 47 | */ 48 | @ReactMethod 49 | fun unSubscribeDevice(params: ReadableMap) { 50 | if (ReactParamsCheck.checkParams(arrayOf(Constant.DEVID), params)) { 51 | ThingHomeSdk.getTransferInstance().unSubscribeDevice(params.getString(DEVID)) 52 | } 53 | } 54 | 55 | @ReactMethod 56 | fun registerTransferDataListener(params: ReadableMap) { 57 | if (ReactParamsCheck.checkParams(arrayOf(Constant.DEVID), params)) { 58 | ThingHomeSdk.getTransferInstance().registerTransferDataListener(object : IThingDataCallback { 59 | override fun onSuccess(var1: TransferDataBean){ 60 | val map = Arguments.createMap() 61 | map.putString("devId", params.getString(DEVID)) 62 | map.putMap("data", TuyaReactUtils.parseToWritableMap(var1)) 63 | map.putString("type", "onSuccess"); 64 | BridgeUtils.singleTransferListener(reactApplicationContext, map, params.getString(DEVID) as String) 65 | } 66 | 67 | override fun onError(var1: String, var2: String){ 68 | val map = Arguments.createMap() 69 | map.putString("devId", params.getString(DEVID)) 70 | map.putString("var1", var1) 71 | map.putString("var2", var2) 72 | map.putString("type", "onError"); 73 | BridgeUtils.singleTransferListener(reactApplicationContext, map, params.getString(DEVID) as String) 74 | } 75 | }) 76 | } 77 | } 78 | 79 | @ReactMethod 80 | fun unRegisterTransferDataListener(params: ReadableMap) { 81 | } 82 | @ReactMethod 83 | fun stopConnect() { 84 | ThingHomeSdk.getTransferInstance().stopConnect() 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /android/src/main/java/com/tuya/smart/rnsdk/home/TuyaHomeMemberModule.kt: -------------------------------------------------------------------------------- 1 | package com.tuya.smart.rnsdk.home 2 | 3 | import com.facebook.react.bridge.* 4 | import com.thingclips.smart.home.sdk.ThingHomeSdk 5 | import com.thingclips.smart.home.sdk.bean.MemberBean 6 | import com.thingclips.smart.home.sdk.callback.IThingGetMemberListCallback 7 | import com.thingclips.smart.home.sdk.callback.IThingMemberResultCallback 8 | import com.tuya.smart.rnsdk.utils.Constant 9 | import com.tuya.smart.rnsdk.utils.JsonUtils 10 | import com.tuya.smart.rnsdk.utils.ReactParamsCheck 11 | import com.tuya.smart.rnsdk.utils.TuyaReactUtils 12 | 13 | class TuyaHomeMemberModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) { 14 | override fun getName(): String { 15 | return "TuyaHomeMemberModule" 16 | } 17 | /* 添加成员 */ 18 | @ReactMethod 19 | fun addMember(params: ReadableMap, promise: Promise) { 20 | if (ReactParamsCheck.checkParams(arrayOf(Constant.HOMEID, Constant.COUNTRYCODE, Constant.USERACCOUNT, Constant.NAME, Constant.ADMIN), params)) { 21 | ThingHomeSdk.getMemberInstance().addMember( 22 | params.getDouble(Constant.HOMEID).toLong(), 23 | params.getString(Constant.COUNTRYCODE), 24 | params.getString(Constant.USERACCOUNT), 25 | params.getString(Constant.NAME), 26 | params.getBoolean(Constant.ADMIN), 27 | object : IThingMemberResultCallback { 28 | override fun onSuccess(var1: MemberBean){ 29 | promise.resolve(TuyaReactUtils.parseToWritableMap(var1)) 30 | } 31 | 32 | override fun onError(var1: String, var2: String){ 33 | promise.reject(var1,var2) 34 | } 35 | } 36 | ) 37 | } 38 | } 39 | /* 移除Home下面的成员 */ 40 | @ReactMethod 41 | fun removeMember(params: ReadableMap, promise: Promise) { 42 | if (ReactParamsCheck.checkParams(arrayOf(Constant.MEMBERID),params)) { 43 | ThingHomeSdk.getMemberInstance().removeMember(params.getDouble(Constant.MEMBERID).toLong(), Constant.getIResultCallback(promise)) 44 | } 45 | } 46 | /* 更新成员备注名和权限 */ 47 | @ReactMethod 48 | fun updateMember(params: ReadableMap, promise: Promise) { 49 | if (ReactParamsCheck.checkParams(arrayOf(Constant.MEMBERID, Constant.NAME, Constant.ADMIN),params)) { 50 | ThingHomeSdk.getMemberInstance().updateMember(params.getDouble(Constant.MEMBERID).toLong(),params.getString(Constant.NAME),params.getBoolean(Constant.ADMIN), Constant.getIResultCallback(promise)) 51 | } 52 | } 53 | 54 | /* 查询Home下面的成员列表 */ 55 | @ReactMethod 56 | fun queryMemberList(params: ReadableMap, promise: Promise) { 57 | if (ReactParamsCheck.checkParams(arrayOf(Constant.HOMEID),params)) { 58 | ThingHomeSdk.getMemberInstance().queryMemberList(params.getDouble(Constant.HOMEID).toLong(),object : IThingGetMemberListCallback { 59 | override fun onSuccess(var1: List){ 60 | promise.resolve(TuyaReactUtils.parseToWritableArray(JsonUtils.toJsonArray(var1))) 61 | } 62 | 63 | override fun onError(var1: String, var2: String){ 64 | promise.reject(var1,var2) 65 | } 66 | }) 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /ios/RNTuyaSdk/Group/TuyaRNGroupModule.m: -------------------------------------------------------------------------------- 1 | // 2 | // TuyaRNGroupModule.m 3 | // TuyaRnDemo 4 | // 5 | // Created by 浩天 on 2019/2/28. 6 | // Copyright © 2019年 Facebook. All rights reserved. 7 | // 8 | 9 | #import "TuyaRNGroupModule.h" 10 | #import 11 | #import "TuyaRNUtils.h" 12 | #import 13 | 14 | 15 | 16 | @implementation TuyaRNGroupModule 17 | 18 | RCT_EXPORT_MODULE(TuyaGroupModule) 19 | 20 | RCT_EXPORT_METHOD(initWithOptions:(NSDictionary *)params) { 21 | 22 | } 23 | 24 | RCT_EXPORT_METHOD(onDestory:(NSDictionary *)params) { 25 | 26 | } 27 | 28 | 29 | // 创建群组: 30 | RCT_EXPORT_METHOD(createGroup:(NSDictionary *)params resolver:(RCTPromiseResolveBlock)resolver rejecter:(RCTPromiseRejectBlock)rejecter) { 31 | [ThingSmartGroup createGroupWithName:params[@"name"] productId:params[@"productId"] homeId:[params[@"homeId"] integerValue] devIdList:params[@"devIds"] success:^(ThingSmartGroup *group) { 32 | if (resolver) { 33 | resolver([group yy_modelToJSONObject]); 34 | } 35 | } failure:^(NSError *error) { 36 | [TuyaRNUtils rejecterWithError:error handler:rejecter]; 37 | }]; 38 | } 39 | 40 | 41 | // 群组列表获取: 42 | RCT_EXPORT_METHOD(queryDeviceListToAddGroup:(NSDictionary *)params resolver:(RCTPromiseResolveBlock)resolver rejecter:(RCTPromiseRejectBlock)rejecter) { 43 | [ThingSmartGroup getDevList:params[@"productId"] homeId:[params[@"homeId"] integerValue] success:^(NSArray *list) { 44 | NSMutableArray *res = [NSMutableArray array]; 45 | for (ThingSmartGroupDevListModel *item in list) { 46 | NSDictionary *dic = [item yy_modelToJSONObject]; 47 | [res addObject:dic]; 48 | } 49 | if (resolver) { 50 | resolver(res); 51 | } 52 | } failure:^(NSError *error) { 53 | [TuyaRNUtils rejecterWithError:error handler:rejecter]; 54 | }]; 55 | } 56 | 57 | // 群组修改名称: 58 | RCT_EXPORT_METHOD(updateGroupName:(NSDictionary *)params resolver:(RCTPromiseResolveBlock)resolver rejecter:(RCTPromiseRejectBlock)rejecter) { 59 | ThingSmartGroup *smartGroup = [ThingSmartGroup groupWithGroupId:params[@"groupID"]]; 60 | [smartGroup updateGroupName:params[@"name"] success:^{ 61 | if (resolver) { 62 | resolver(@"success"); 63 | } 64 | } failure:^(NSError *error) { 65 | [TuyaRNUtils rejecterWithError:error handler:rejecter]; 66 | }]; 67 | } 68 | 69 | // 解散群组: 70 | RCT_EXPORT_METHOD(dismissGroup:(NSDictionary *)params resolver:(RCTPromiseResolveBlock)resolver rejecter:(RCTPromiseRejectBlock)rejecter) { 71 | ThingSmartGroup *smartGroup = [ThingSmartGroup groupWithGroupId:params[@"groupID"]]; 72 | [smartGroup dismissGroup:^{ 73 | if (resolver) { 74 | resolver(@"success"); 75 | } 76 | } failure:^(NSError *error) { 77 | [TuyaRNUtils rejecterWithError:error handler:rejecter]; 78 | }]; 79 | } 80 | 81 | 82 | // 发送群组控制命令: 83 | RCT_EXPORT_METHOD(publishDps:(NSDictionary *)params resolver:(RCTPromiseResolveBlock)resolver rejecter:(RCTPromiseRejectBlock)rejecter) { 84 | ThingSmartGroup *smartGroup = [ThingSmartGroup groupWithGroupId:params[@"groupID"]]; 85 | NSDictionary *dps = @{@"1": @(YES)}; 86 | [smartGroup publishDps:dps success:^{ 87 | if (resolver) { 88 | resolver(@"success"); 89 | } 90 | } failure:^(NSError *error) { 91 | [TuyaRNUtils rejecterWithError:error handler:rejecter]; 92 | }]; 93 | 94 | } 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | @end 106 | -------------------------------------------------------------------------------- /ios/RNTuyaSdk/Feedback/TuyaRNFeedBackModule.m: -------------------------------------------------------------------------------- 1 | // 2 | // TuyaRNFeedBackModule.m 3 | // TuyaRnDemo 4 | // 5 | // Created by 浩天 on 2019/2/28. 6 | // Copyright © 2019年 Facebook. All rights reserved. 7 | // 8 | 9 | #import "TuyaRNFeedBackModule.h" 10 | #import 11 | #import "TuyaRNUtils.h" 12 | #import "YYModel.h" 13 | 14 | @interface TuyaRNFeedBackModule() 15 | @property (nonatomic, strong) ThingSmartFeedback *smartFeedback; 16 | @end 17 | 18 | 19 | @implementation TuyaRNFeedBackModule 20 | 21 | RCT_EXPORT_MODULE(TuyaFeedBackModule) 22 | 23 | RCT_EXPORT_METHOD(initWithOptions:(NSDictionary *)params) { 24 | 25 | } 26 | 27 | // 获取反馈列表: 28 | RCT_EXPORT_METHOD(getFeedbackMsg:(NSDictionary *)params resolver:(RCTPromiseResolveBlock)resolver rejecter:(RCTPromiseRejectBlock)rejecter) { 29 | ThingSmartFeedback *feedBack = [[ThingSmartFeedback alloc] init]; 30 | self.smartFeedback = feedBack; 31 | [feedBack getFeedbackList:params[@"hdId"] hdType:[params[@"hdType"] unsignedIntegerValue] success:^(NSArray *list) { 32 | NSMutableArray *res = [NSMutableArray array]; 33 | for (ThingSmartFeedbackModel *item in list) { 34 | NSDictionary *dic = [item yy_modelToJSONObject]; 35 | [res addObject:dic]; 36 | } 37 | if (resolver) { 38 | resolver(res); 39 | } 40 | } failure:^(NSError *error) { 41 | [TuyaRNUtils rejecterWithError:error handler:rejecter]; 42 | }]; 43 | 44 | } 45 | 46 | 47 | 48 | // 获取反馈类型列表: 49 | RCT_EXPORT_METHOD(getFeedbackType:(RCTPromiseResolveBlock)resolver rejecter:(RCTPromiseRejectBlock)rejecter) { 50 | ThingSmartFeedback *feedBack = [[ThingSmartFeedback alloc] init]; 51 | self.smartFeedback = feedBack; 52 | [feedBack getFeedbackTypeList:^(NSArray *list) { 53 | 54 | NSMutableArray *res = [NSMutableArray array]; 55 | for (ThingSmartFeedbackTypeListModel *item in list) { 56 | NSDictionary *dic = [item yy_modelToJSONObject]; 57 | [res addObject:dic]; 58 | } 59 | if (resolver) { 60 | resolver(res); 61 | } 62 | } failure:^(NSError *error) { 63 | [TuyaRNUtils rejecterWithError:error handler:rejecter]; 64 | }]; 65 | } 66 | 67 | 68 | // 新增反馈: 69 | RCT_EXPORT_METHOD(addMsg:(NSDictionary *)params resolver:(RCTPromiseResolveBlock)resolver rejecter:(RCTPromiseRejectBlock)rejecter) { 70 | ThingSmartFeedback *feedBack = [[ThingSmartFeedback alloc] init]; 71 | self.smartFeedback = feedBack; 72 | [feedBack addFeedback:params[@"message"] hdId:params[@"hdId"] hdType:[params[@"hdType"] integerValue] contact:params[@"contact"] success:^{ 73 | if (resolver) { 74 | resolver(@"success"); 75 | } 76 | } failure:^(NSError *error) { 77 | [TuyaRNUtils rejecterWithError:error handler:rejecter]; 78 | }]; 79 | } 80 | 81 | 82 | // 反馈消息管理: 83 | RCT_EXPORT_METHOD(getFeedbackList:(RCTPromiseResolveBlock)resolver rejecter:(RCTPromiseRejectBlock)rejecter) { 84 | ThingSmartFeedback *feedBack = [[ThingSmartFeedback alloc] init]; 85 | self.smartFeedback = feedBack; 86 | [feedBack getFeedbackTalkList:^(NSArray *list) { 87 | NSMutableArray *res = [NSMutableArray array]; 88 | for (ThingSmartFeedbackTalkListModel *item in list) { 89 | NSDictionary *dic = [item yy_modelToJSONObject]; 90 | [res addObject:dic]; 91 | } 92 | if (resolver) { 93 | resolver(res); 94 | } 95 | } failure:^(NSError *error) { 96 | [TuyaRNUtils rejecterWithError:error handler:rejecter]; 97 | }]; 98 | } 99 | 100 | 101 | 102 | @end 103 | -------------------------------------------------------------------------------- /android/src/main/java/com/tuya/smart/rnsdk/device/TuyaOTAModule.kt: -------------------------------------------------------------------------------- 1 | package com.tuya.smart.rnsdk.device 2 | 3 | import com.facebook.react.bridge.* 4 | import com.thingclips.smart.android.device.bean.UpgradeInfoBean 5 | import com.thingclips.smart.home.sdk.ThingHomeSdk 6 | import com.thingclips.smart.sdk.api.IGetOtaInfoCallback 7 | import com.thingclips.smart.sdk.api.IOtaListener 8 | import com.thingclips.smart.sdk.api.IThingOta 9 | import com.thingclips.smart.sdk.bean.OTAErrorMessageBean 10 | import com.tuya.smart.rnsdk.utils.* 11 | import com.tuya.smart.rnsdk.utils.Constant.DEVID 12 | 13 | 14 | class TuyaOTAModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) { 15 | override fun getName(): String { 16 | return "TuyaOTAModule" 17 | } 18 | 19 | var iTuyaOta: IThingOta?=null 20 | /* 获取固件升级信息 */ 21 | @ReactMethod 22 | fun getOtaInfo(params: ReadableMap,promise: Promise) { 23 | if (ReactParamsCheck.checkParams(arrayOf(DEVID), params)) { 24 | getIoat(params.getString(DEVID) as String).getOtaInfo(object : IGetOtaInfoCallback { 25 | override fun onSuccess(list: List) { 26 | promise.resolve(TuyaReactUtils.parseToWritableArray( 27 | JsonUtils.toJsonArray(list))) 28 | } 29 | 30 | override fun onFailure(code: String, error: String){ 31 | promise.reject(code,error) 32 | } 33 | }) 34 | } 35 | } 36 | /* 设置升级状态回调 */ 37 | @ReactMethod 38 | fun startOta(params: ReadableMap) { 39 | if (ReactParamsCheck.checkParams(arrayOf(DEVID), params)) { 40 | iTuyaOta = getIoat(params.getString(DEVID) as String) 41 | iTuyaOta?.setOtaListener(object : IOtaListener { 42 | override fun onSuccess(otaType: Int) { 43 | var map=Arguments.createMap(); 44 | map.putInt("otaType",otaType) 45 | map.putString("type","onSuccess") 46 | BridgeUtils.hardwareUpgradeListener(reactApplicationContext,map,params.getString(DEVID) as String) 47 | } 48 | 49 | override fun onStatusChanged(otaStatus: Int, otaType: Int) { 50 | // 51 | } 52 | 53 | override fun onTimeout(otaType: Int) { 54 | // 55 | } 56 | 57 | override fun onFailureWithText(otaType: Int, code: String, messageBean: OTAErrorMessageBean) { 58 | // 59 | } 60 | 61 | override fun onFailure(otaType: Int, code: String, error: String) { 62 | var map=Arguments.createMap(); 63 | map.putInt("otaType",otaType) 64 | map.putString("error",error) 65 | map.putString("code",code) 66 | map.putString("type","onFailure") 67 | BridgeUtils.hardwareUpgradeListener(reactApplicationContext,map,params.getString(DEVID) as String) 68 | } 69 | 70 | override fun onProgress(otaType: Int, progress: Int) { 71 | var map=Arguments.createMap(); 72 | map.putInt("otaType",otaType) 73 | map.putInt("progress",progress) 74 | map.putString("type","onProgress") 75 | BridgeUtils.hardwareUpgradeListener(reactApplicationContext,map,params.getString(DEVID) as String) 76 | } 77 | }) 78 | iTuyaOta?.startOta() 79 | } 80 | } 81 | @ReactMethod 82 | fun onDestroy(){ 83 | iTuyaOta?.onDestroy() 84 | } 85 | fun getIoat(devId:String): IThingOta { 86 | return ThingHomeSdk.newOTAInstance(devId) 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /ios/RNTuyaSdk/Home/TuyaRNHomeDataManagerModule.m: -------------------------------------------------------------------------------- 1 | // 2 | // TuyaRNHomeDataManagerModule.m 3 | // TuyaRnDemo 4 | // 5 | // Created by 浩天 on 2019/3/2. 6 | // Copyright © 2019年 Facebook. All rights reserved. 7 | // 8 | 9 | #import "TuyaRNHomeDataManagerModule.h" 10 | #import 11 | #import "TuyaRNUtils+Cache.h" 12 | #import "TuyaRNUtils+DeviceParser.h" 13 | 14 | #define kTuyaRNHomeDataManagerModuleHomeId @"homeId" 15 | #define kTuyaRNHomeDataManagerModuleRoomId @"roomId" 16 | 17 | @interface TuyaRNHomeDataManagerModule() 18 | 19 | @property (strong, nonatomic) ThingSmartRoom *smartRoom; 20 | 21 | @end 22 | 23 | @implementation TuyaRNHomeDataManagerModule 24 | 25 | RCT_EXPORT_MODULE(TuyaHomeDataManagerModule) 26 | 27 | RCT_EXPORT_METHOD(getHomeRoomList:(RCTPromiseResolveBlock)resolver rejecter:(RCTPromiseRejectBlock)rejecter) { 28 | 29 | } 30 | 31 | RCT_EXPORT_METHOD(getHomeDeviceList:(NSDictionary *)params resolver:(RCTPromiseResolveBlock)resolver rejecter:(RCTPromiseRejectBlock)rejecter) { 32 | 33 | } 34 | 35 | RCT_EXPORT_METHOD(getHomeGroupList:(NSDictionary *)params resolver:(RCTPromiseResolveBlock)resolver rejecter:(RCTPromiseRejectBlock)rejecter) { 36 | 37 | } 38 | 39 | 40 | RCT_EXPORT_METHOD(getGroupBean:(NSDictionary *)params resolver:(RCTPromiseResolveBlock)resolver rejecter:(RCTPromiseRejectBlock)rejecter) { 41 | 42 | } 43 | 44 | RCT_EXPORT_METHOD(getDeviceBean:(NSDictionary *)params resolver:(RCTPromiseResolveBlock)resolver rejecter:(RCTPromiseRejectBlock)rejecter) { 45 | 46 | } 47 | 48 | RCT_EXPORT_METHOD(getGroupRoomBean:(NSDictionary *)params resolver:(RCTPromiseResolveBlock)resolver rejecter:(RCTPromiseRejectBlock)rejecter) { 49 | 50 | } 51 | 52 | 53 | RCT_EXPORT_METHOD(getRoomBean:(NSDictionary *)params resolver:(RCTPromiseResolveBlock)resolver rejecter:(RCTPromiseRejectBlock)rejecter) { 54 | 55 | } 56 | 57 | RCT_EXPORT_METHOD(getDeviceRoomBean:(NSDictionary *)params resolver:(RCTPromiseResolveBlock)resolver rejecter:(RCTPromiseRejectBlock)rejecter) { 58 | 59 | } 60 | 61 | RCT_EXPORT_METHOD(getGroupDeviceList:(NSDictionary *)params resolver:(RCTPromiseResolveBlock)resolver rejecter:(RCTPromiseRejectBlock)rejecter) { 62 | 63 | } 64 | 65 | 66 | RCT_EXPORT_METHOD(getMeshGroupList:(NSDictionary *)params resolver:(RCTPromiseResolveBlock)resolver rejecter:(RCTPromiseRejectBlock)rejecter) { 67 | 68 | } 69 | 70 | RCT_EXPORT_METHOD(getMeshDeviceList:(NSDictionary *)params resolver:(RCTPromiseResolveBlock)resolver rejecter:(RCTPromiseRejectBlock)rejecter) { 71 | 72 | } 73 | 74 | RCT_EXPORT_METHOD(getRoomDeviceList:(NSDictionary *)params resolver:(RCTPromiseResolveBlock)resolver rejecter:(RCTPromiseRejectBlock)rejecter) { 75 | 76 | //获取room下的Device 77 | NSNumber *homeId = params[kTuyaRNHomeDataManagerModuleHomeId]; 78 | if(!homeId) { 79 | homeId = [TuyaRNUtils currentHomeId]; 80 | } 81 | NSNumber *roomId = params[kTuyaRNHomeDataManagerModuleRoomId]; 82 | 83 | //获取room下的设备 84 | self.smartRoom = [ThingSmartRoom roomWithRoomId:roomId.longLongValue homeId:homeId.longLongValue]; 85 | if(resolver) { 86 | NSMutableDictionary *roomDic = [[NSMutableDictionary alloc] initWithCapacity:2]; 87 | [roomDic setObject:getValidDataForDeviceModel(self.smartRoom.deviceList) forKey:@"deviceList"]; 88 | [roomDic setObject:getValidDataForGroupModel(self.smartRoom.groupList) forKey:@"groupList"]; 89 | resolver(roomDic); 90 | } 91 | } 92 | 93 | RCT_EXPORT_METHOD(getRoomGroupList:(NSDictionary *)params resolver:(RCTPromiseResolveBlock)resolver rejecter:(RCTPromiseRejectBlock)rejecter) { 94 | 95 | } 96 | 97 | RCT_EXPORT_METHOD(getHomeBean:(NSDictionary *)params resolver:(RCTPromiseResolveBlock)resolver rejecter:(RCTPromiseRejectBlock)rejecter) { 98 | 99 | } 100 | 101 | @end 102 | -------------------------------------------------------------------------------- /android/src/main/java/com/tuya/smart/rnsdk/utils/Constant.kt: -------------------------------------------------------------------------------- 1 | package com.tuya.smart.rnsdk.utils 2 | 3 | import com.facebook.react.bridge.Promise 4 | import com.thingclips.smart.sdk.api.IResultCallback 5 | 6 | object Constant { 7 | 8 | /** 9 | * 在创建自动化条件时标识符 10 | */ 11 | const val ENTITY_TYPE_TIMER = 6 12 | const val ENTITY_TYPE_WEATHER = 3 13 | const val ENTITY_TYPE_DEVICE = 1 14 | const val ENTITY_TYPE = "entityType" 15 | 16 | const val SUCCESS = "success" 17 | const val FAILED = "failed" 18 | 19 | const val NEEDLOGIN = "needLogin" 20 | const val API_REQUEST_ERROR = "api request error" 21 | 22 | const val COUNTRYCODE = "countryCode" 23 | const val EMAIL = "email" 24 | const val PHONENUMBER = "phoneNumber" 25 | const val VALIDATECODE = "validateCode" 26 | const val PASSWORD = "password" 27 | const val NEWPASSWORD = "newPassword" 28 | const val CODE = "code" 29 | const val UID = "uid" 30 | const val KEY = "key" 31 | const val SECRET = "secret" 32 | const val USERID = "userId" 33 | const val ACCESSTOKEN = "accessToken" 34 | const val TOKEN = "token" 35 | const val FILEPATH = "filePath" 36 | const val TEMPUNITENUM = "tempUnitEnum" 37 | 38 | const val DEVID = "devId" 39 | const val GROUPID = "groupId" 40 | const val MESHID = "meshId" 41 | const val HOMEID = "homeId" 42 | const val NAME = "name" 43 | const val LON = "lon" 44 | const val LAT = "lat" 45 | const val GEONAME = "geoName" 46 | const val ROOMID = "roomId" 47 | const val ACTION = "action" 48 | const val IDLIST = "idList" 49 | const val PRODUCTID = "productId" 50 | const val DEVIDLIST = "devIdList" 51 | const val ROMMS = "rooms" 52 | const val MEMBERID = "memberId" 53 | const val USERACCOUNT = "userAccount" 54 | const val ADMIN = "admin" 55 | const val SSID = "ssid" 56 | const val TIME = "time" 57 | const val ACTIVATORMODELENUM = "ActivatorModelEnum" 58 | const val COMMAND = "command" 59 | const val DATAPOINTTYPEENUM = "DataPointTypeEnum" 60 | const val NUMBER = "number" 61 | const val STARTTIME = "startTime" 62 | const val DEVIDS = "devIds" 63 | const val IDS = "ids" 64 | const val OPERATOR = "operator" 65 | 66 | const val TASKNAME = "taskName" 67 | const val LOOPS = "loops" 68 | const val DPS = "dps" 69 | const val TIMERID = "timerId" 70 | const val INSTRUCT = "instruct" 71 | const val DPID = "dpId" 72 | const val ISOPEN = "isOpen" 73 | const val STATUS = "status" 74 | const val SHAREID = "shareId" 75 | const val GROUPNAME = "groupName" 76 | const val GROUPLISTENER = "GroupListener" 77 | const val SHOWFAHRENHEIT = "showFahrenheit" 78 | 79 | const val LOCALID = "localId" 80 | 81 | const val CITYID = "cityId" 82 | const val CITYIDS = "cityIdS" 83 | const val CONDITIONLISTS = "conditionList" 84 | 85 | const val RULE = "rule" 86 | const val CONDITIONS = "conditions" 87 | const val SCENETASK = "SceneTask" 88 | const val SCENEID = "sceneId" 89 | const val SCENEIDS = "sceneIds" 90 | const val TASK = "task" 91 | const val TYPE = "type" 92 | const val DISPLAY = "display" 93 | const val VALUE = "value" 94 | const val TASKS = "tasks" 95 | const val RANGE = "range" 96 | const val ID = "id" 97 | const val MESEAGE = "message" 98 | const val CONTACT = "contact" 99 | const val HDID = "hdId" 100 | const val HDTYPE = "hdType" 101 | const val RULES = "rules" 102 | const val DPVALUE = "dpvalue" 103 | 104 | const val STICKYONTOP = "stickyOnTop" 105 | const val BACKGROUND = "background" 106 | const val MATCHTYPE = "matchType" 107 | const val ALIASID = "aliasId" 108 | const val PUSHPROVIDER = "pushProvider" 109 | fun getIResultCallback(promise: Promise): IResultCallback? { 110 | return object : IResultCallback { 111 | override fun onSuccess() { 112 | promise.resolve(Constant.SUCCESS) 113 | } 114 | 115 | override fun onError(code: String?, error: String?) { 116 | promise.reject(code, error) 117 | } 118 | } 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /android/src/main/java/com/tuya/smart/rnsdk/device/TuyaGatewayModule.kt: -------------------------------------------------------------------------------- 1 | package com.tuya.smart.rnsdk.device 2 | 3 | import com.facebook.react.bridge.* 4 | import com.thingclips.smart.home.sdk.ThingHomeSdk 5 | import com.thingclips.smart.sdk.api.ISubDevListener 6 | import com.tuya.smart.rnsdk.utils.* 7 | 8 | class TuyaGatewayModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) { 9 | override fun getName(): String { 10 | return "TuyaGatewayModule" 11 | } 12 | 13 | @ReactMethod 14 | fun publishDps(params: ReadableMap,promise: Promise) { 15 | if (ReactParamsCheck.checkParams(arrayOf(Constant.DEVID,Constant.LOCALID,Constant.DPS), params)) { 16 | ThingHomeSdk.newGatewayInstance(params.getString(Constant.DEVID)).publishDps(params.getString(Constant.LOCALID),params.getString(Constant.DPS),Constant.getIResultCallback(promise)) 17 | } 18 | } 19 | 20 | 21 | 22 | @ReactMethod 23 | fun broadcastDps(params: ReadableMap,promise: Promise) { 24 | if (ReactParamsCheck.checkParams(arrayOf(Constant.DEVID,Constant.DPS), params)) { 25 | ThingHomeSdk.newGatewayInstance(params.getString(Constant.DEVID)).broadcastDps(params.getString(Constant.DPS),Constant.getIResultCallback(promise)) 26 | } 27 | } 28 | 29 | @ReactMethod 30 | fun multicastDps(params: ReadableMap,promise: Promise) { 31 | if (ReactParamsCheck.checkParams(arrayOf(Constant.DEVID,Constant.LOCALID,Constant.DPS), params)) { 32 | ThingHomeSdk.newGatewayInstance(params.getString(Constant.DEVID)).multicastDps(params.getString(Constant.LOCALID),params.getString(Constant.DPS),Constant.getIResultCallback(promise)) 33 | } 34 | } 35 | 36 | 37 | 38 | @ReactMethod 39 | fun registerSubDevListener(params: ReadableMap) { 40 | if (ReactParamsCheck.checkParams(arrayOf(Constant.DEVID), params)) { 41 | ThingHomeSdk.newGatewayInstance(params.getString(Constant.DEVID)).registerSubDevListener(object : ISubDevListener { 42 | override fun onSubDevDpUpdate(var1: String, var2: String){ 43 | val map = Arguments.createMap() 44 | map.putString("devId", var1) 45 | map.putString("dpStr", var2) 46 | map.putString("type", "onSubDevDpUpdate"); 47 | BridgeUtils.subDevListener(reactApplicationContext, map, params.getString(Constant.DEVID) as String) 48 | } 49 | 50 | override fun onSubDevRemoved(var1: String){ 51 | val map = Arguments.createMap() 52 | map.putString("devId", var1) 53 | map.putString("type", "onSubDevRemoved"); 54 | BridgeUtils.subDevListener(reactApplicationContext, map, params.getString(Constant.DEVID) as String) 55 | } 56 | 57 | override fun onSubDevAdded(var1: String){ 58 | val map = Arguments.createMap() 59 | map.putString("devId", var1) 60 | map.putString("type", "onSubDevAdded"); 61 | BridgeUtils.subDevListener(reactApplicationContext, map, params.getString(Constant.DEVID) as String) 62 | } 63 | 64 | override fun onSubDevInfoUpdate(var1: String){ 65 | val map = Arguments.createMap() 66 | map.putString("devId", var1) 67 | map.putString("type", "onSubDevInfoUpdate"); 68 | BridgeUtils.subDevListener(reactApplicationContext, map, params.getString(Constant.DEVID) as String) 69 | } 70 | 71 | override fun onSubDevStatusChanged(var1: List, var2: List){ 72 | val map = Arguments.createMap() 73 | map.putArray("data1", TuyaReactUtils.parseToWritableArray( 74 | JsonUtils.toJsonArray(var1))) 75 | map.putArray("data2", TuyaReactUtils.parseToWritableArray( 76 | JsonUtils.toJsonArray(var2))); 77 | map.putString("type", "onSubDevStatusChanged"); 78 | BridgeUtils.subDevListener(reactApplicationContext, map, params.getString(Constant.DEVID) as String) 79 | } 80 | }) 81 | } 82 | } 83 | 84 | @ReactMethod 85 | fun unRegisterSubDevListener(params: ReadableMap) { 86 | if (ReactParamsCheck.checkParams(arrayOf(Constant.DEVID), params)) { 87 | ThingHomeSdk.newGatewayInstance(params.getString(Constant.DEVID)).unRegisterSubDevListener() 88 | } 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /ios/RNTuyaSdk/Utils/Listener/TuyaRNGroupListener.m: -------------------------------------------------------------------------------- 1 | // 2 | // TuyaRNGroupListener.m 3 | // TuyaRnDemo 4 | // 5 | // Created by Elon on 2019/3/7. 6 | // Copyright © 2019 Facebook. All rights reserved. 7 | // 8 | 9 | #import "TuyaRNGroupListener.h" 10 | #import 11 | #import 12 | #import 13 | #import "TuyaRNEventEmitter.h" 14 | 15 | @interface TuyaRNGroupListener() 16 | 17 | @property (nonatomic, strong) NSMutableArray *listenGroupArr; 18 | @end 19 | 20 | @implementation TuyaRNGroupListener 21 | 22 | + (instancetype)shareInstance { 23 | static TuyaRNGroupListener *listenerInstance = nil; 24 | static dispatch_once_t onceToken; 25 | dispatch_once(&onceToken, ^{ 26 | listenerInstance = [TuyaRNGroupListener new]; 27 | }); 28 | return listenerInstance; 29 | } 30 | 31 | 32 | - (instancetype)init { 33 | if (self = [super init]) { 34 | _listenGroupArr = [NSMutableArray new]; 35 | } 36 | return self; 37 | } 38 | 39 | + (void)registerGroup:(ThingSmartGroup *)group { 40 | 41 | __block BOOL exist = NO; 42 | [[TuyaRNGroupListener shareInstance].listenGroupArr enumerateObjectsUsingBlock:^(ThingSmartGroup * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { 43 | if ([obj.groupModel.groupId isEqualToString:group.groupModel.groupId]) { 44 | exist = YES; 45 | *stop = YES; 46 | } 47 | }]; 48 | 49 | group.delegate = [TuyaRNGroupListener shareInstance]; 50 | 51 | if (!exist) { 52 | if ([TuyaRNGroupListener shareInstance].listenGroupArr.count == 0) { 53 | } 54 | [[TuyaRNGroupListener shareInstance].listenGroupArr addObject:group]; 55 | } 56 | } 57 | 58 | + (void)removeDevice:(ThingSmartGroup *)group { 59 | [[[TuyaRNGroupListener shareInstance].listenGroupArr mutableCopy] enumerateObjectsUsingBlock:^(ThingSmartGroup * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { 60 | if ([obj.groupModel.groupId isEqualToString:group.groupModel.groupId]) { 61 | obj.delegate = nil; 62 | [[TuyaRNGroupListener shareInstance].listenGroupArr removeObject:obj]; 63 | *stop = YES; 64 | } 65 | }]; 66 | } 67 | 68 | 69 | #pragma mark - 70 | #pragma mark - TuyaSmartGroupDelegate 71 | /// 群组dp数据更新 72 | - (void)group:(ThingSmartGroup *)group dpsUpdate:(NSDictionary *)dps { 73 | NSDictionary *dic = @{ 74 | @"devId": group.groupModel.groupId, 75 | @"dps": dps, 76 | @"type": @"onDpUpdate" 77 | }; 78 | 79 | [TuyaRNEventEmitter ty_sendEvent:[kTYEventEmitterGroupInfoEvent stringByAppendingFormat:@"//%@", group.groupModel.groupId] withBody:dic]; 80 | } 81 | 82 | /// 群组信息更新 83 | - (void)groupInfoUpdate:(ThingSmartGroup *)group { 84 | 85 | NSDictionary *dic = @{ 86 | @"id": group.groupModel.groupId, 87 | @"type": @"onGroupInfoUpdate" 88 | }; 89 | 90 | [TuyaRNEventEmitter ty_sendEvent:[kTYEventEmitterGroupInfoEvent stringByAppendingFormat:@"//%@", group.groupModel.groupId] withBody:dic]; 91 | } 92 | 93 | /// 群组移除 94 | - (void)groupRemove:(ThingSmartGroup *)group { 95 | NSDictionary *dic = @{ 96 | @"id": group.groupModel.groupId, 97 | @"type": @"onGroupRemoved" 98 | }; 99 | 100 | [TuyaRNEventEmitter ty_sendEvent:[kTYEventEmitterGroupInfoEvent stringByAppendingFormat:@"//%@", group.groupModel.groupId] withBody:dic]; 101 | } 102 | 103 | ///// zigbee 设备加入到网关群组响应 104 | ///// 1:超过场景数上限 2:子设备超时 3:设置值超出范围 4:写文件错误 5:其他错误 105 | //- (void)group:(TuyaSmartGroup *)group addResponseCode:(NSArray *)responseCode { 106 | // NSDictionary *dic = @{ 107 | // @"id": group.groupModel.groupId, 108 | // @"type": @"onGroupRemoved" 109 | // }; 110 | // [TuyaRNEventEmitter ty_sendEvent:[kTYEventEmitterGroupInfoEvent stringByAppendingFormat:@"//%@", group.groupModel.groupId] withBody:dic]; 111 | //} 112 | // 113 | ///// zigbee 设备从网关群组移除响应 114 | ///// 1:超过场景数上限 2:子设备超时 3:设置值超出范围 4:写文件错误 5:其他错误 115 | //- (void)group:(TuyaSmartGroup *)group removeResponseCode:(NSArray *)responseCode { 116 | // NSDictionary *dic = @{ 117 | // @"id": group.groupModel.groupId, 118 | // @"type": @"onGroupRemoved" 119 | // }; 120 | // [TuyaRNEventEmitter ty_sendEvent:[kTYEventEmitterGroupInfoEvent stringByAppendingFormat:@"//%@", group.groupModel.groupId] withBody:dic]; 121 | //} 122 | 123 | 124 | @end 125 | -------------------------------------------------------------------------------- /android/src/main/java/com/tuya/smart/rnsdk/core/TuyaCoreModule.kt: -------------------------------------------------------------------------------- 1 | package com.tuya.smart.rnsdk.core 2 | 3 | import android.app.Application 4 | import android.content.Context 5 | import android.text.TextUtils 6 | import android.util.Log 7 | import com.alibaba.fastjson.JSON 8 | import com.alibaba.fastjson.JSONArray 9 | import com.facebook.react.bridge.* 10 | import com.thingclips.smart.home.sdk.ThingHomeSdk 11 | import com.thingclips.smart.sdk.api.INeedLoginListener 12 | import com.thingclips.smart.sdk.api.IThingDataCallback 13 | import com.tuya.smart.rnsdk.utils.Constant.API_REQUEST_ERROR 14 | import com.tuya.smart.rnsdk.utils.Constant.NEEDLOGIN 15 | import com.tuya.smart.rnsdk.utils.TYRCTCommonUtil 16 | import com.tuya.smart.rnsdk.utils.TuyaReactUtils 17 | import java.util.HashMap 18 | 19 | 20 | class TuyaCoreModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) { 21 | 22 | companion object { 23 | fun initTuyaSDk(appKey:String,appSecret:String,application: Application){ 24 | ThingHomeSdk.init(application, appKey, appSecret) 25 | } 26 | 27 | fun initTuyaSDKWithoutOptions(application: Application){ 28 | ThingHomeSdk.init(application) 29 | } 30 | 31 | fun setSDKDebug(open:Boolean){ 32 | ThingHomeSdk.setDebugMode(open) 33 | } 34 | } 35 | 36 | override fun getName(): String { 37 | return "TuyaCoreModule" 38 | } 39 | 40 | /** 41 | * 不带参数的初始化,appKey和appSecret要写在AndroidManifest中 42 | */ 43 | @ReactMethod 44 | @Deprecated("Android can't initSDK in react-native,it should be used in application") 45 | fun initWithoutOptions() { 46 | ThingHomeSdk.init(reactApplicationContext.applicationContext as Application?); 47 | ThingHomeSdk.setOnNeedLoginListener { 48 | TuyaReactUtils.sendEvent(reactApplicationContext, NEEDLOGIN, null) 49 | } 50 | } 51 | 52 | @ReactMethod 53 | @Deprecated("Android can't initSDK in react-native,it should be used in application") 54 | fun initWithOptions(params: ReadableMap) { 55 | val appKey = params.getString("appKey") 56 | val appSecret = params.getString("appSecret") 57 | ThingHomeSdk.init(reactApplicationContext.applicationContext as Application?, appKey, appSecret) 58 | ThingHomeSdk.setOnNeedLoginListener(INeedLoginListener() { 59 | fun onNeedLogin(context: Context?) { 60 | TuyaReactUtils.sendEvent(reactApplicationContext, NEEDLOGIN, null) 61 | } 62 | }) 63 | } 64 | 65 | @ReactMethod 66 | fun setOnNeedLoginListener(){ 67 | ThingHomeSdk.setOnNeedLoginListener(INeedLoginListener() { 68 | fun onNeedLogin(context: Context?) { 69 | TuyaReactUtils.sendEvent(reactApplicationContext, NEEDLOGIN, null) 70 | } 71 | }) 72 | } 73 | 74 | 75 | 76 | @ReactMethod 77 | fun exitApp() { 78 | ThingHomeSdk.onDestroy(); 79 | } 80 | 81 | @ReactMethod 82 | fun apiRequest(params: ReadableMap, promise: Promise) { 83 | val callback = object : IThingDataCallback { 84 | override fun onSuccess(data: Any?) { 85 | if (data is Boolean) { 86 | Log.e("apiRequest", data.toString()) 87 | promise.resolve("success") 88 | return 89 | } 90 | 91 | if(data is JSONArray){ 92 | val writableArray = TYRCTCommonUtil.parseToWritableArray(data as com.alibaba.fastjson.JSONArray) 93 | promise.resolve(writableArray) 94 | return 95 | } 96 | val writableMap = TYRCTCommonUtil.parseToWritableMap(data) 97 | promise.resolve(writableMap) 98 | 99 | } 100 | 101 | override fun onError(errorCode: String?, errorMsg: String?) { 102 | promise.reject(errorCode, errorMsg) 103 | } 104 | 105 | } 106 | 107 | // val withoutSession = params.getBoolean("withoutSession") 108 | val withoutSession = false 109 | val apiName = params.getString("apiName") 110 | val apiVersion = params.getString("version") 111 | val postData = TYRCTCommonUtil.parseToMap(params.getMap("postData")) 112 | if (TextUtils.isEmpty(apiName)) { 113 | promise.reject(API_REQUEST_ERROR, "ApiName is empty") 114 | return 115 | } 116 | 117 | if (withoutSession) { 118 | ThingHomeSdk.getRequestInstance().requestWithApiNameWithoutSession(apiName, apiVersion, postData, Any::class.java, callback) 119 | } else { 120 | ThingHomeSdk.getRequestInstance().requestWithApiName(apiName, apiVersion, postData, Any::class.java,callback) 121 | } 122 | 123 | } 124 | 125 | } 126 | 127 | -------------------------------------------------------------------------------- /android/src/main/java/com/tuya/smart/rnsdk/feedback/TuyaFeedBackModule.kt: -------------------------------------------------------------------------------- 1 | package com.tuya.smart.rnsdk.feedback 2 | 3 | import com.facebook.react.bridge.* 4 | import com.thingclips.smart.home.sdk.ThingHomeSdk 5 | import com.thingclips.smart.sdk.api.IThingDataCallback 6 | import com.thingclips.smart.sdk.bean.feedback.FeedbackBean 7 | import com.thingclips.smart.sdk.bean.feedback.FeedbackMsgBean 8 | import com.thingclips.smart.sdk.bean.feedback.FeedbackTypeRespBean 9 | import com.tuya.smart.rnsdk.utils.Constant 10 | import com.tuya.smart.rnsdk.utils.Constant.HDID 11 | import com.tuya.smart.rnsdk.utils.Constant.HDTYPE 12 | import com.tuya.smart.rnsdk.utils.JsonUtils 13 | import com.tuya.smart.rnsdk.utils.ReactParamsCheck 14 | import com.tuya.smart.rnsdk.utils.TuyaReactUtils 15 | 16 | 17 | class TuyaFeedBackModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) { 18 | override fun getName(): String { 19 | return "TuyaFeedBackModule" 20 | } 21 | 22 | /*获取反馈列表*/ 23 | @ReactMethod 24 | fun getFeedbackList(promise: Promise) { 25 | ThingHomeSdk.getThingFeekback().getFeedbackManager().getFeedbackList(object : IThingDataCallback> { 26 | override fun onSuccess(var1: List) { 27 | promise.resolve(TuyaReactUtils.parseToWritableArray(JsonUtils.toJsonArray(var1!!))) 28 | } 29 | 30 | override fun onError(var1: String, var2: String) { 31 | promise.reject(var1, var2) 32 | } 33 | }) 34 | } 35 | 36 | 37 | /*获取反馈列表*/ 38 | @ReactMethod 39 | fun getFeedbackType(promise: Promise) { 40 | ThingHomeSdk.getThingFeekback().getFeedbackManager().getFeedbackType(object : IThingDataCallback> { 41 | override fun onSuccess(var1: List) { 42 | promise.resolve(TuyaReactUtils.parseToWritableArray(JsonUtils.toJsonArray(var1!!))) 43 | } 44 | 45 | override fun onError(var1: String, var2: String) { 46 | promise.reject(var1, var2) 47 | } 48 | }) 49 | } 50 | 51 | 52 | /*添加反馈*/ 53 | @ReactMethod 54 | fun addFeedback(params: ReadableMap, promise: Promise) { 55 | if (ReactParamsCheck.checkParams(arrayOf(Constant.MESEAGE, Constant.CONTACT, Constant.HDID, Constant.HDTYPE), params)) { 56 | ThingHomeSdk.getThingFeekback().getFeedbackManager().addFeedback(params.getString(Constant.MESEAGE), params.getString(Constant.CONTACT), 57 | params.getString(HDID), params.getInt(HDTYPE), 58 | object : IThingDataCallback { 59 | override fun onSuccess(var1: FeedbackMsgBean) { 60 | promise.resolve(TuyaReactUtils.parseToWritableMap(var1!!)) 61 | } 62 | 63 | override fun onError(var1: String, var2: String) { 64 | promise.reject(var1, var2) 65 | } 66 | }) 67 | } 68 | } 69 | 70 | 71 | /*获取反馈消息列表*/ 72 | @ReactMethod 73 | fun getFeedbackMsg(params: ReadableMap, promise: Promise) { 74 | if (ReactParamsCheck.checkParams(arrayOf(Constant.HDID, Constant.HDTYPE), params)) { 75 | ThingHomeSdk.getThingFeekback().getFeedbackMsg(params.getString(HDID), params.getInt(HDTYPE)) 76 | .getMsgList( 77 | object : IThingDataCallback> { 78 | override fun onSuccess(var1: List) { 79 | promise.resolve(TuyaReactUtils.parseToWritableArray(JsonUtils.toJsonArray(var1!!))) 80 | } 81 | 82 | override fun onError(var1: String, var2: String) { 83 | promise.reject(var1, var2) 84 | } 85 | }) 86 | } 87 | } 88 | 89 | 90 | /*添加新反馈*/ 91 | @ReactMethod 92 | fun addMsg(params: ReadableMap, promise: Promise) { 93 | if (ReactParamsCheck.checkParams(arrayOf(Constant.HDID, Constant.HDTYPE, Constant.MESEAGE, Constant.CONTACT), params)) { 94 | ThingHomeSdk.getThingFeekback().getFeedbackMsg(params.getString(HDID), params.getInt(HDTYPE)) 95 | .addMsg(params.getString(Constant.MESEAGE), params.getString(Constant.CONTACT), 96 | object : IThingDataCallback { 97 | override fun onSuccess(var1: FeedbackMsgBean) { 98 | promise.resolve(TuyaReactUtils.parseToWritableMap(var1!!)) 99 | } 100 | 101 | override fun onError(var1: String, var2: String) { 102 | promise.reject(var1, var2) 103 | } 104 | }) 105 | } 106 | } 107 | 108 | } 109 | -------------------------------------------------------------------------------- /ios/RNTuyaSdk/Home/TuyaRNHomeManagerModule.m: -------------------------------------------------------------------------------- 1 | // 2 | // TuyaRNHomeManagerModule.m 3 | // TuyaRnDemo 4 | // 5 | // Created by 浩天 on 2019/2/28. 6 | // Copyright © 2019年 Facebook. All rights reserved. 7 | // 8 | 9 | #import "TuyaRNHomeManagerModule.h" 10 | #import 11 | #import 12 | #import 13 | #import "YYModel.h" 14 | #import "TuyaRNUtils.h" 15 | #import "TuyaRNHomeManagerListener.h" 16 | #import "TuyaRNHomeListener.h" 17 | 18 | #define kTuyaHomeManagerModuleName @"name" 19 | #define kTuyaHomeManagerModuleLon @"lon" 20 | #define kTuyaHomeManagerModuleLat @"lat" 21 | #define kTuyaHomeManagerModuleGeoName @"geoName" 22 | #define kTuyaHomeManagerModuleRooms @"rooms" 23 | #define kTuyaHomeManagerModuleHomeId @"homeId" 24 | #define kTuyaHomeManagerModuleAction @"action" 25 | 26 | 27 | @interface TuyaRNHomeManagerModule() 28 | 29 | @property (nonatomic, strong) ThingSmartHomeManager *homeManager; 30 | @property (nonatomic, strong) ThingSmartRequest *request; 31 | 32 | @end 33 | 34 | @implementation TuyaRNHomeManagerModule 35 | 36 | RCT_EXPORT_MODULE(TuyaHomeManagerModule) 37 | 38 | /** 39 | * 获取家庭列表 40 | * 41 | * @param listener 42 | */ 43 | RCT_EXPORT_METHOD(queryHomeList:(RCTPromiseResolveBlock)resolver rejecter:(RCTPromiseRejectBlock)rejecter) { 44 | 45 | [self.homeManager getHomeListWithSuccess:^(NSArray *homes) { 46 | 47 | if (homes.count == 0) { 48 | if (resolver) { 49 | resolver(@[]); 50 | } 51 | return; 52 | } 53 | 54 | NSMutableArray *list = [NSMutableArray array]; 55 | for (ThingSmartHomeModel *homeModel in homes) { 56 | NSDictionary *dic = [homeModel yy_modelToJSONObject]; 57 | NSMutableDictionary *homeDic = [NSMutableDictionary dictionaryWithDictionary:dic]; 58 | [homeDic setObject:[NSNumber numberWithLongLong:homeModel.homeId] forKey:@"homeId"]; 59 | [list addObject:homeDic]; 60 | } 61 | 62 | if (resolver) { 63 | resolver(list); 64 | } 65 | } failure:^(NSError *error) { 66 | 67 | }]; 68 | } 69 | 70 | /** 71 | * 创建家庭 72 | * @param name 家庭名称 73 | * @param lon 经度 74 | * @param lat 纬度 75 | * @param geoName 家庭地理位置名称 76 | * @param rooms 房间列表 77 | * @param callback 78 | */ 79 | RCT_EXPORT_METHOD(createHome:(NSDictionary *)params resolver:(RCTPromiseResolveBlock)resolver rejecter:(RCTPromiseRejectBlock)rejecter) { 80 | 81 | NSString *name = params[kTuyaHomeManagerModuleName]; 82 | NSString *geoName = params[kTuyaHomeManagerModuleGeoName]; 83 | NSNumber *lat = params[kTuyaHomeManagerModuleLat]; 84 | NSNumber *lon = params[kTuyaHomeManagerModuleLon]; 85 | NSArray *rooms = params[kTuyaHomeManagerModuleRooms]; 86 | 87 | double latValue = lat.doubleValue; 88 | double lonValue = lon.doubleValue; 89 | 90 | [self.homeManager addHomeWithName:name geoName:geoName rooms:rooms latitude:latValue longitude:lonValue success:^(long long result) { 91 | [TuyaRNUtils resolverWithHandler:resolver]; 92 | } failure:^(NSError *error) { 93 | [TuyaRNUtils rejecterWithError:error handler:rejecter]; 94 | }]; 95 | } 96 | 97 | /** 98 | * 注册家庭信息的变更 99 | * 有:家庭的增加、删除、信息变更、分享列表的变更和服务器连接成功的监听 100 | * 101 | * @param listener 102 | */ 103 | RCT_EXPORT_METHOD(registerTuyaHomeChangeListener:(NSDictionary *)params resolver:(RCTPromiseResolveBlock)resolver rejecter:(RCTPromiseRejectBlock)rejecter) { 104 | 105 | NSNumber *homeIdNum = params[kTuyaHomeManagerModuleHomeId]; 106 | if (!homeIdNum || homeIdNum.longLongValue <= 0) { 107 | return; 108 | } 109 | //开始监听家庭的情况 110 | [[TuyaRNHomeManagerListener sharedInstance] registerSmartHomeManager:[ThingSmartHomeManager new]]; 111 | [[TuyaRNHomeListener shareInstance] registerHomeChangeWithSmartHome:[ThingSmartHome homeWithHomeId:homeIdNum.longLongValue]]; 112 | } 113 | 114 | /** 115 | * 注销家庭信息的变更 116 | * 117 | * @param listener 118 | */ 119 | RCT_EXPORT_METHOD(unregisterTuyaHomeChangeListener:(NSDictionary *)params resolver:(RCTPromiseResolveBlock)resolver rejecter:(RCTPromiseRejectBlock)rejecter) { 120 | 121 | //结束家庭的监听情况 122 | [[TuyaRNHomeManagerListener sharedInstance] removeSmartHomeManager]; 123 | [[TuyaRNHomeListener shareInstance] removeHomeChangeSmartHome]; 124 | 125 | } 126 | 127 | RCT_EXPORT_METHOD(joinFamily:(NSDictionary *)params resolver:(RCTPromiseResolveBlock)resolver rejecter:(RCTPromiseRejectBlock)rejecter) { 128 | NSNumber *homeIdNum = params[kTuyaHomeManagerModuleHomeId]; 129 | NSString *action = params[kTuyaHomeManagerModuleAction]; 130 | ThingSmartHome *newHome = [ThingSmartHome homeWithHomeId:homeIdNum.longLongValue]; 131 | 132 | [newHome joinFamilyWithAccept:action.boolValue success:^(BOOL result) { 133 | [TuyaRNUtils resolverWithHandler:resolver]; 134 | } failure:^(NSError *error) { 135 | [TuyaRNUtils rejecterWithError:error handler:rejecter]; 136 | }]; 137 | } 138 | 139 | RCT_EXPORT_METHOD(onDestory:(NSDictionary *)params) { 140 | 141 | } 142 | 143 | #pragma mark - 144 | #pragma mark - init 145 | - (ThingSmartHomeManager *)homeManager { 146 | if (!_homeManager) { 147 | _homeManager = [[ThingSmartHomeManager alloc] init]; 148 | } 149 | return _homeManager; 150 | } 151 | 152 | - (ThingSmartRequest *)request { 153 | if (!_request) { 154 | _request = [ThingSmartRequest new]; 155 | } 156 | return _request; 157 | } 158 | 159 | @end 160 | -------------------------------------------------------------------------------- /ios/RNTuyaSdk/Home/TuyaRNHomeMemberModule.m: -------------------------------------------------------------------------------- 1 | // 2 | // TuyaRNHomeMemberModule.m 3 | // TuyaRnDemo 4 | // 5 | // Created by 浩天 on 2019/3/1. 6 | // Copyright © 2019年 Facebook. All rights reserved. 7 | // 8 | 9 | #import "TuyaRNHomeMemberModule.h" 10 | #import "TuyaRNUtils.h" 11 | #import "YYModel.h" 12 | #import 13 | #import 14 | 15 | #define kTuyaRNHomeMemberModuleHomeId @"homeId" 16 | #define kTuyaRNHomeMemberModuleCountryCode @"countryCode" 17 | #define kTuyaRNHomeMemberModuleUserAccount @"userAccount" 18 | #define kTuyaRNHomeMemberModuleName @"name" 19 | #define kTuyaRNHomeMemberModuleAdmin @"admin" 20 | #define kTuyaRNHomeMemberModuleMemberId @"memberId" 21 | //#define kTuyaRNHomeMemberModule 22 | 23 | @interface TuyaRNHomeMemberModule() 24 | 25 | @property (nonatomic, strong) ThingSmartHomeMember *homeMember; 26 | @property (nonatomic, strong) ThingSmartHome *smartHome; 27 | 28 | @end 29 | 30 | @implementation TuyaRNHomeMemberModule 31 | 32 | RCT_EXPORT_MODULE(TuyaHomeMemberModule) 33 | 34 | /** 35 | * 给这个Home下面添加成员 36 | * 37 | * @param countryCode 国家码 38 | * @param userAccount 用户名 39 | * @param name 昵称 40 | * @param admin 是否拥有管理员权限 41 | * @param callback 42 | */ 43 | 44 | RCT_EXPORT_METHOD(addMember:(NSDictionary *)params resolver:(RCTPromiseResolveBlock)resolver rejecter:(RCTPromiseRejectBlock)rejecter) { 45 | 46 | ThingSmartHome *smartHome = [self smartHomeWithParams:params]; 47 | 48 | ThingSmartHomeAddMemberRequestModel *requestModel = [[ThingSmartHomeAddMemberRequestModel alloc] init]; 49 | 50 | NSString *name = params[kTuyaRNHomeMemberModuleName]; 51 | NSString *userAccount = params[kTuyaRNHomeMemberModuleUserAccount]; 52 | NSString *countryCode = params[kTuyaRNHomeMemberModuleCountryCode]; 53 | NSString *admin = params[kTuyaRNHomeMemberModuleAdmin]; 54 | 55 | requestModel.name = name; 56 | requestModel.account = userAccount; 57 | requestModel.countryCode = countryCode; 58 | requestModel.autoAccept = NO; 59 | requestModel.role = admin.boolValue ? ThingHomeRoleType_Admin : ThingHomeRoleType_Member; 60 | 61 | [smartHome addHomeMemberWithAddMemeberRequestModel:requestModel success:^(NSDictionary *dict) { 62 | if (resolver) { 63 | resolver(dict); 64 | } 65 | } failure:^(NSError *error) { 66 | [TuyaRNUtils rejecterWithError:error handler:rejecter]; 67 | }]; 68 | } 69 | 70 | /** 71 | * 移除Home下面的成员 72 | * 73 | * @param id 74 | * @param callback 75 | */ 76 | RCT_EXPORT_METHOD(removeMember:(NSDictionary *)params resolver:(RCTPromiseResolveBlock)resolver rejecter:(RCTPromiseRejectBlock)rejecter) { 77 | 78 | NSNumber *memberId = params[kTuyaRNHomeMemberModuleMemberId]; 79 | [self.homeMember removeHomeMemberWithMemberId:memberId.longLongValue success:^{ 80 | [TuyaRNUtils resolverWithHandler:resolver]; 81 | } failure:^(NSError *error) { 82 | [TuyaRNUtils rejecterWithError:error handler:rejecter]; 83 | }]; 84 | } 85 | 86 | /** 87 | * 更新成员备注名和权限 88 | * @param name 备注名 如果不更改备注名,传入从memberBean获取的nickName 89 | * @param admin 是否是管理员 90 | * @param callback 91 | */ 92 | RCT_EXPORT_METHOD(updateMember:(NSDictionary *)params resolver:(RCTPromiseResolveBlock)resolver rejecter:(RCTPromiseRejectBlock)rejecter) { 93 | 94 | NSNumber *memberId = params[kTuyaRNHomeMemberModuleMemberId]; 95 | NSString *admin = params[kTuyaRNHomeMemberModuleAdmin]; 96 | 97 | ThingSmartHomeMemberRequestModel *requestModel = [[ThingSmartHomeMemberRequestModel alloc] init]; 98 | requestModel.memberId = memberId.longLongValue; 99 | requestModel.name = params[kTuyaRNHomeMemberModuleName]; 100 | requestModel.role = admin.boolValue ? ThingHomeRoleType_Admin : ThingHomeRoleType_Member; 101 | 102 | [self.homeMember updateHomeMemberInfoWithMemberRequestModel:requestModel success:^{ 103 | [TuyaRNUtils resolverWithHandler:resolver]; 104 | } failure:^(NSError *error) { 105 | [TuyaRNUtils rejecterWithError:error handler:rejecter]; 106 | }]; 107 | } 108 | 109 | /** 110 | * 查询Home下面的成员列表 111 | * 112 | */ 113 | RCT_EXPORT_METHOD(queryMemberList:(NSDictionary *)params resolver:(RCTPromiseResolveBlock)resolver rejecter:(RCTPromiseRejectBlock)rejecter) { 114 | 115 | self.smartHome = [self smartHomeWithParams:params]; 116 | [self.smartHome getHomeMemberListWithSuccess:^(NSArray *memberList) { 117 | if (memberList.count == 0) { 118 | if (resolver) { 119 | resolver(@[]); 120 | } 121 | return; 122 | } 123 | NSMutableArray *memberDicList = [NSMutableArray array]; 124 | for (ThingSmartHomeMemberModel *memberModel in memberList) { 125 | NSDictionary *dic = [memberModel yy_modelToJSONObject]; 126 | if (dic) { 127 | [memberDicList addObject:dic]; 128 | } 129 | } 130 | if (resolver) { 131 | resolver(memberDicList); 132 | } 133 | } failure:^(NSError *error) { 134 | [TuyaRNUtils rejecterWithError:error handler:rejecter]; 135 | }]; 136 | 137 | } 138 | 139 | #pragma mark - 140 | #pragma mark - init 141 | - (ThingSmartHome *)smartHomeWithParams:(NSDictionary *)params { 142 | long long homeId = ((NSNumber *)params[kTuyaRNHomeMemberModuleHomeId]).longLongValue; 143 | return [ThingSmartHome homeWithHomeId:homeId]; 144 | } 145 | 146 | - (ThingSmartHomeMember *)homeMember { 147 | if (!_homeMember) { 148 | _homeMember = [[ThingSmartHomeMember alloc] init]; 149 | } 150 | return _homeMember; 151 | } 152 | 153 | @end 154 | -------------------------------------------------------------------------------- /ios/RNTuyaSdk/Activator/TuyaRNActivatorModule.m: -------------------------------------------------------------------------------- 1 | // 2 | // TuyaRNActivatorModule.m 3 | // TuyaRnDemo 4 | // 5 | // Created by 浩天 on 2019/2/28. 6 | // Copyright © 2019年 Facebook. All rights reserved. 7 | // 8 | 9 | #import "TuyaRNActivatorModule.h" 10 | #import 11 | #import 12 | #import 13 | #import "TuyaRNUtils+Network.h" 14 | #import "YYModel.h" 15 | 16 | #define kTuyaRNActivatorModuleHomeId @"homeId" 17 | #define kTuyaRNActivatorModuleSSID @"ssid" 18 | #define kTuyaRNActivatorModulePassword @"password" 19 | #define kTuyaRNActivatorModuleActivatorMode @"type" 20 | #define kTuyaRNActivatorModuleOverTime @"time" 21 | #define kTuyaRNActivatorModuleAcccessToken @"token" 22 | #define kTuyaRNActivatorModuleDeviceId @"devId" 23 | 24 | static TuyaRNActivatorModule * activatorInstance = nil; 25 | 26 | @interface TuyaRNActivatorModule() 27 | 28 | @property(copy, nonatomic) RCTPromiseResolveBlock promiseResolveBlock; 29 | @property(copy, nonatomic) RCTPromiseRejectBlock promiseRejectBlock; 30 | 31 | @end 32 | 33 | @implementation TuyaRNActivatorModule 34 | 35 | RCT_EXPORT_MODULE(TuyaActivatorModule) 36 | 37 | /** 开始配网 38 | * @param homeId 当前用户的homeId 39 | * @param ssid 配网之后,设备工作WiFi的名称。(家庭网络) 40 | * @param password 配网之后,设备工作WiFi的密码。(家庭网络) 41 | * @param activatorModel: 现在给设备配网有以下两种方式: 42 | ActivatorModelEnum.TY_EZ: 传入该参数则进行EZ配网 43 | ActivatorModelEnum.TY_AP: 传入该参数则进行AP配网 44 | * @param timeout 配网的超时时间设置,默认是100s. 45 | */ 46 | RCT_EXPORT_METHOD(initActivator:(NSDictionary *)params resolver:(RCTPromiseResolveBlock)resolver rejecter:(RCTPromiseRejectBlock)rejecter) { 47 | 48 | NSNumber *homeId = params[kTuyaRNActivatorModuleHomeId]; 49 | NSString *ssid = params[kTuyaRNActivatorModuleSSID]; 50 | NSString *password = params[kTuyaRNActivatorModulePassword]; 51 | NSNumber *time = params[kTuyaRNActivatorModuleOverTime]; 52 | NSString *type = params[kTuyaRNActivatorModuleActivatorMode]; 53 | // NSString *token = params[kTuyaRNActivatorModuleActivatorToken]; 54 | 55 | ThingActivatorMode mode = ThingActivatorModeEZ; 56 | 57 | if ([type isEqualToString:@"THING_AP"]) { 58 | mode = ThingActivatorModeAP; 59 | } else if([type isEqualToString:@"THING_EZ"]) { 60 | mode = ThingActivatorModeEZ; 61 | } else if([type isEqualToString:@"THING_4G_GATEWAY"]) { 62 | mode = ThingActivatorModeAP4GGateway; 63 | } else if([type isEqualToString:@"THING_QR"]) { 64 | mode = ThingActivatorModeQRCode; 65 | } 66 | 67 | if (activatorInstance == nil) { 68 | activatorInstance = [TuyaRNActivatorModule new]; 69 | } 70 | 71 | [ThingSmartActivator sharedInstance].delegate = activatorInstance; 72 | activatorInstance.promiseResolveBlock = resolver; 73 | activatorInstance.promiseRejectBlock = rejecter; 74 | 75 | [[ThingSmartActivator sharedInstance] getTokenWithHomeId:homeId.longLongValue success:^(NSString *result) { 76 | //开始配置网络: 77 | [[ThingSmartActivator sharedInstance] startConfigWiFi:mode ssid:ssid password:password token:result timeout:time.doubleValue]; 78 | } failure:^(NSError *error) { 79 | [TuyaRNUtils rejecterWithError:error handler:rejecter]; 80 | }]; 81 | } 82 | 83 | 84 | RCT_EXPORT_METHOD(stopConfig:(RCTPromiseResolveBlock)resolver rejecter:(RCTPromiseRejectBlock)rejecter) { 85 | 86 | [[ThingSmartActivator sharedInstance] stopConfigWiFi]; 87 | } 88 | 89 | //ZigBee子设备配网需要ZigBee网关设备云在线的情况下才能发起,且子设备处于配网状态。 90 | 91 | RCT_EXPORT_METHOD(newGwSubDevActivator:(NSDictionary *)params resolver:(RCTPromiseResolveBlock)resolver rejecter:(RCTPromiseRejectBlock)rejecter) { 92 | 93 | NSString *deviceId = params[kTuyaRNActivatorModuleDeviceId]; 94 | NSNumber *time = params[kTuyaRNActivatorModuleOverTime]; 95 | 96 | if (activatorInstance == nil) { 97 | activatorInstance = [TuyaRNActivatorModule new]; 98 | } 99 | 100 | [ThingSmartActivator sharedInstance].delegate = activatorInstance; 101 | activatorInstance.promiseResolveBlock = resolver; 102 | activatorInstance.promiseRejectBlock = rejecter; 103 | 104 | [[ThingSmartActivator sharedInstance] activeSubDeviceWithGwId:deviceId timeout:time.doubleValue]; 105 | 106 | } 107 | 108 | RCT_EXPORT_METHOD(stopNewGwSubDevActivatorConfig:(NSDictionary *)params resolver:(RCTPromiseResolveBlock)resolver rejecter:(RCTPromiseRejectBlock)rejecter) { 109 | 110 | NSString *deviceId = params[kTuyaRNActivatorModuleDeviceId]; 111 | [[ThingSmartActivator sharedInstance] stopActiveSubDeviceWithGwId:deviceId]; 112 | } 113 | 114 | /** 115 | 获取wifi信息 116 | */ 117 | RCT_EXPORT_METHOD(getCurrentWifi:(NSDictionary *)params success:(RCTResponseSenderBlock)succ failure:(RCTResponseErrorBlock)fail) { 118 | NSString *ssid = [ThingSmartActivator currentWifiSSID]; 119 | if ([ssid isKindOfClass:[NSString class]] && ssid.length > 0) { 120 | succ(@[ssid]); 121 | } else { 122 | fail(nil); 123 | } 124 | } 125 | 126 | 127 | //判断网络 128 | RCT_EXPORT_METHOD(openNetworkSettings:(NSDictionary *)params resolver :(RCTPromiseResolveBlock)resolver rejecter:(RCTPromiseRejectBlock)rejecter) { 129 | 130 | [TuyaRNUtils openNetworkSettings]; 131 | 132 | } 133 | 134 | RCT_EXPORT_METHOD(onDestory:(RCTPromiseResolveBlock)resolver rejecter:(RCTPromiseRejectBlock)rejecter) { 135 | 136 | } 137 | 138 | 139 | #pragma mark - 140 | #pragma mark - delegate 141 | /// 配网状态更新的回调,wifi单品,zigbee网关,zigbee子设备 142 | - (void)activator:(ThingSmartActivator *)activator didReceiveDevice:(ThingSmartDeviceModel *)deviceModel error:(NSError *)error { 143 | 144 | if (error) { 145 | if (activatorInstance.promiseRejectBlock) { 146 | [TuyaRNUtils rejecterWithError:error handler:activatorInstance.promiseRejectBlock]; 147 | } 148 | return; 149 | } 150 | 151 | //开始回调 152 | if (activatorInstance.promiseResolveBlock) { 153 | self.promiseResolveBlock([deviceModel yy_modelToJSONObject]); 154 | } 155 | } 156 | 157 | @end 158 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # @owowagency/react-native-tuya 2 | 3 | This is a fork of [TuyaInc/tuyasmart-home-sdk-react-native](https://github.com/TuyaInc/tuyasmart-home-sdk-react-native), fixing a lot of issues we came across and a better install guide. It also uses TypeScript. We use it currently in multiple projects for clients and it is stable. 4 | 5 | Some features are not implemented, feel free to send a PR for those missing features. Unfortunately there is no demo yet 6 | 7 | ## Feature Overview 8 | 9 | Tuya Smart APP SDK provides the interface package for the communication with hardware and Tuya Cloud to accelerate the application development process, including the following features: 10 | 11 | Hardware functions (network configuration, control, status reporting, regular tasks, groups, firmware upgrades, sharing) 12 | Account system (phone number, email registration, login, password reset and other general account functions) 13 | Tuya Cloud HTTP API interface package 14 | 15 | ## Getting started 16 | 17 | ``` 18 | npm install @owowagency/react-native-tuya 19 | ``` 20 | 21 | This library contains native code which is automatically linked in React Native >= 0.59. For iOS, run `cd ios && pod install`. 22 | 23 | ## Installation 24 | 25 | In the Tuya development environment create a new app and make sure you have an "App key", "App secret" [Read how to do this](https://tuyainc.github.io/tuyasmart_home_ios_sdk_doc/en/resource/Preparation.html). 26 | 27 | ### iOS 28 | 29 | Download the security dependency and add it to the project as [explained here](https://developer.tuya.com/en/docs/app-development/integrate-sdk?id=Ka5d52ewngdoi#title-1-Integrate%20with%20the%20SDK). 30 | 31 | In `ios/AppDelegate.m`, add the following import; 32 | 33 | ```obj-c 34 | #import 35 | ``` 36 | 37 | Then, under the `roootView.backgroundColor` line in the same file, add this: 38 | 39 | ```obj-c 40 | #ifdef DEBUG 41 | [[ThingSmartSDK sharedInstance] setDebugMode:YES]; 42 | #endif 43 | 44 | [[ThingSmartSDK sharedInstance] startWithAppKey:@"xxx" secretKey:@"xxx"]; 45 | ``` 46 | 47 | Now replace the `xxx` with your app key and secret key. 48 | 49 | ### Android 50 | 51 | Assuming you already have created an app in the Tuya development environment (otherwise follow the iOS steps before this), follow [these steps](https://developer.tuya.com/en/docs/app-development/integrated?id=Ka69nt96cw0uj#title-5-Step%203%3A%20Integrate%20with%20security%20component). You should now have an app key, app secret and security dependency for Android 52 | 53 | Open your `AndroidManifest.xml` and put the following **in the `` tag**: 54 | 55 | ```xml 56 | 59 | 62 | ``` 63 | 64 | Replace the `xxx` with your app key and secret key. 65 | 66 | Now open `MainApplication.java` and add the following import to the top: 67 | 68 | ```java 69 | import com.tuya.smart.rnsdk.core.TuyaCoreModule; 70 | ``` 71 | 72 | Change the `onCreate` function to look like this: 73 | 74 | ```java 75 | @Override 76 | public void onCreate() { 77 | super.onCreate(); 78 | SoLoader.init(this, /* native exopackage */ false); 79 | initializeFlipper(this); // Remove this line if you don't want Flipper enabled 80 | TuyaCoreModule.Companion.initTuyaSDKWithoutOptions(this); 81 | } 82 | ``` 83 | 84 | Now you can try to build, but you'll probably run into an error saying that it can't choose between `libc++_shared` or something. One fix for this (don't know if it's the best fix) is to open `android/app/build.gradle` and add this; 85 | 86 | ``` 87 | android { 88 | ... 89 | packagingOptions { 90 | pickFirst '**/armeabi-v7a/libc++_shared.so' 91 | pickFirst '**/x86/libc++_shared.so' 92 | pickFirst '**/arm64-v8a/libc++_shared.so' 93 | pickFirst '**/x86_64/libc++_shared.so' 94 | pickFirst '**/x86/libjsc.so' 95 | pickFirst '**/armeabi-v7a/libjsc.so' 96 | } 97 | } 98 | ``` 99 | 100 | ## Usage 101 | 102 | Now you can actually use the methods in this package. Unfortunately I don't have time to document them all, so it is advised to read the source code, but here's a start. 103 | 104 | To login with an existing account: 105 | 106 | ```js 107 | import { loginWithEmail } from '@owowagency/react-native-tuya'; 108 | 109 | await loginWithEmail({ 110 | countryCode: '+1', 111 | email: 'you@example.com', 112 | password: 'testtest' 113 | }); 114 | ``` 115 | 116 | To register a new account you first need to validate the email address. And then actually register using the code in the email. 117 | 118 | ```js 119 | import { getRegisterEmailValidateCode, registerAccountWithEmail } from '@owowagency/react-native-tuya'; 120 | 121 | await getRegisterEmailValidateCode({ 122 | countryCode: '+1', 123 | email: 'you@example.com' 124 | }); 125 | 126 | ... 127 | 128 | await registerAccountWithEmail({ 129 | countryCode: '+1', 130 | email: 'you@example.com', 131 | password: 'testtest', 132 | validateCode: 'xxxxxx' 133 | }) 134 | ``` 135 | 136 | To get the currently logged in user: 137 | 138 | ```js 139 | import { getCurrentUser } from '@owowagency/react-native-tuya'; 140 | 141 | const user = await getCurrentUser(); 142 | ``` 143 | 144 | ## Local Development 145 | 146 | ### `yarn start` 147 | 148 | Runs the project in development/watch mode. Your project will be rebuilt upon changes. TSDX has a special logger for you convenience. Error messages are pretty printed and formatted for compatibility VS Code's Problems tab. 149 | 150 | 151 | 152 | Your library will be rebuilt if you make edits. 153 | 154 | ### `yarn build` 155 | 156 | Bundles the package to the `dist` folder. 157 | The package is optimized and bundled with Rollup into multiple formats (CommonJS, UMD, and ES Module). 158 | 159 | 160 | -------------------------------------------------------------------------------- /android/src/main/java/com/tuya/smart/rnsdk/home/TuyaHomeManagerModule.kt: -------------------------------------------------------------------------------- 1 | package com.tuya.smart.rnsdk.home 2 | 3 | import com.facebook.react.bridge.* 4 | import com.thingclips.smart.home.sdk.ThingHomeSdk 5 | import com.thingclips.smart.home.sdk.api.IThingHomeChangeListener 6 | import com.thingclips.smart.home.sdk.bean.HomeBean 7 | import com.thingclips.smart.home.sdk.callback.IThingGetHomeListCallback 8 | import com.thingclips.smart.home.sdk.callback.IThingHomeResultCallback 9 | import com.thingclips.smart.sdk.bean.DeviceBean 10 | import com.thingclips.smart.sdk.bean.GroupBean 11 | import com.tuya.smart.rnsdk.utils.* 12 | 13 | class TuyaHomeManagerModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) { 14 | override fun getName(): String { 15 | return "TuyaHomeManagerModule" 16 | } 17 | 18 | 19 | /* 获取家庭列表 */ 20 | @ReactMethod 21 | fun queryHomeList(promise: Promise) { 22 | ThingHomeSdk.getHomeManagerInstance().queryHomeList(object : IThingGetHomeListCallback { 23 | override fun onSuccess(var1: List) { 24 | promise.resolve(TuyaReactUtils.parseToWritableArray(JsonUtils.toJsonArray(var1!!))) 25 | } 26 | 27 | override fun onError(var1: String, var2: String) { 28 | promise.reject(var1, var2) 29 | } 30 | }) 31 | } 32 | 33 | /* 创建家庭 */ 34 | @ReactMethod 35 | fun createHome(params: ReadableMap, promise: Promise) { 36 | if (ReactParamsCheck.checkParams(arrayOf(Constant.NAME, Constant.LON, Constant.LAT, Constant.GEONAME, Constant.ROMMS), params)) { 37 | var list = ArrayList() 38 | var length = (params.getArray(Constant.ROMMS) as ReadableArray).size() 39 | for (index in 0 until length) { 40 | list.add((params.getArray(Constant.ROMMS) as ReadableArray).getString(index) as String) 41 | } 42 | ThingHomeSdk.getHomeManagerInstance().createHome( 43 | params.getString(Constant.NAME), 44 | params.getDouble(Constant.LON), 45 | params.getDouble(Constant.LAT), 46 | params.getString(Constant.GEONAME), 47 | list, 48 | getITuyaHomeResultCallback(promise) 49 | ) 50 | 51 | } 52 | } 53 | 54 | 55 | @ReactMethod 56 | fun joinFamily(params: ReadableMap, promise: Promise) { 57 | if (ReactParamsCheck.checkParams(arrayOf(Constant.HOMEID, Constant.ACTION), params)) { 58 | ThingHomeSdk.getMemberInstance().processInvitation( 59 | params.getDouble(Constant.HOMEID).toLong(), 60 | params.getBoolean(Constant.ACTION), 61 | Constant.getIResultCallback(promise) 62 | ) 63 | 64 | } 65 | } 66 | 67 | 68 | /* 注册家庭信息的变更 69 | * 有:家庭的增加、删除、信息变更、分享列表的变更和服务器连接成功的监听 */ 70 | @ReactMethod 71 | fun registerTuyaHomeChangeListener(params: ReadableMap) { 72 | ThingHomeSdk.getHomeManagerInstance().registerThingHomeChangeListener(object : IThingHomeChangeListener { 73 | override fun onHomeInvite(p0: Long, p1: String?) { 74 | val map = Arguments.createMap() 75 | map.putDouble("homeId", p0.toDouble()) 76 | map.putString("homeName", p1) 77 | BridgeUtils.homeChange(reactApplicationContext, map, params.getDouble("homeId")) 78 | } 79 | 80 | override fun onHomeAdded(var1: Long) { 81 | val map = Arguments.createMap() 82 | map.putDouble("homeId", var1.toDouble()) 83 | map.putString("type", "onHomeAdded"); 84 | BridgeUtils.homeChange(reactApplicationContext, map, params.getDouble("homeId")) 85 | } 86 | 87 | override fun onHomeRemoved(var1: Long) { 88 | val map = Arguments.createMap() 89 | map.putDouble("homeId", var1.toDouble()) 90 | map.putString("type", "onHomeRemoved"); 91 | BridgeUtils.homeChange(reactApplicationContext, map, params.getDouble("homeId")) 92 | } 93 | 94 | override fun onHomeInfoChanged(var1: Long) { 95 | val map = Arguments.createMap() 96 | map.putDouble("homeId", var1.toDouble()) 97 | map.putString("type", "onHomeInfoChanged"); 98 | BridgeUtils.homeChange(reactApplicationContext, map, params.getDouble("homeId")) 99 | } 100 | 101 | override fun onSharedDeviceList(var1: List) { 102 | val map = Arguments.createMap() 103 | map.putArray("deviceBeans", TuyaReactUtils.parseToWritableArray(JsonUtils.toJsonArray(var1))) 104 | map.putString("type", "onSharedDeviceList"); 105 | BridgeUtils.homeChange(reactApplicationContext, map, params.getDouble("homeId")) 106 | } 107 | 108 | override fun onSharedGroupList(var1: List) { 109 | val map = Arguments.createMap() 110 | map.putArray("groupBeans", TuyaReactUtils.parseToWritableArray(JsonUtils.toJsonArray(var1))) 111 | map.putString("type", "onSharedGroupList"); 112 | BridgeUtils.homeChange(reactApplicationContext, map, params.getDouble("homeId")) 113 | } 114 | 115 | override fun onServerConnectSuccess() { 116 | val map = Arguments.createMap() 117 | map.putString("type", "onServerConnectSuccess"); 118 | BridgeUtils.homeChange(reactApplicationContext, map, params.getDouble("homeId")) 119 | } 120 | }) 121 | } 122 | 123 | 124 | fun getITuyaHomeResultCallback(promise: Promise): IThingHomeResultCallback? { 125 | return object : IThingHomeResultCallback { 126 | override fun onSuccess(p0: HomeBean?) { 127 | promise.resolve(TuyaReactUtils.parseToWritableMap(p0)) 128 | } 129 | 130 | override fun onError(code: String?, error: String?) { 131 | promise.reject(code, error) 132 | } 133 | } 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /ios/RNTuyaSdk/Core/TuyaRNCoreModule.m: -------------------------------------------------------------------------------- 1 | // 2 | // TuyaCoreApi.m 3 | // TuyaSdkTest 4 | // 5 | // Created by 浩天 on 2019/2/27. 6 | // Copyright © 2019年 Facebook. All rights reserved. 7 | // 8 | 9 | #import "TuyaRNCoreModule.h" 10 | #import 11 | #import 12 | #import 13 | #import 14 | #import "TuyaRNUtils+Network.h" 15 | 16 | #define kTuyaCoreModuleAppkey @"" 17 | #define kTuyaCoreModuleAppSecret @"" 18 | #define kTuyaCoreModuleParamLat @"lat" 19 | #define kTuyaCoreModuleParamLon @"lon" 20 | 21 | #define kTuyaCoreModuleUserDefaultLocation_lat @"ty_rn_lat" 22 | #define kTuyaCoreModuleUserDefaultLocation_lon @"ty_rn_lon" 23 | 24 | @interface TuyaRNCoreModule() 25 | 26 | @property (nonatomic, strong) CLLocationManager *locationManager; 27 | 28 | @end 29 | 30 | 31 | @implementation TuyaRNCoreModule 32 | 33 | RCT_EXPORT_MODULE(TuyaCoreModule) 34 | 35 | RCT_EXPORT_METHOD(initWithOptions:(NSDictionary *)params) { 36 | 37 | NSString *appKey = params[kTuyaCoreModuleAppkey]; 38 | NSString *appSecret = params[kTuyaCoreModuleAppSecret]; 39 | 40 | dispatch_async(dispatch_get_main_queue(), ^{ 41 | // [[TuyaSmartSDK sharedInstance] startWithAppKey:appKey secretKey:appSecret]; 42 | //#ifdef DEBUG 43 | // [TuyaSmartSDK sharedInstance].debugMode = YES; 44 | //#endif 45 | 46 | if (!self.locationManager) { 47 | self.locationManager = [CLLocationManager new]; 48 | self.locationManager.delegate = self; 49 | } 50 | if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusAuthorizedWhenInUse || [CLLocationManager authorizationStatus] == kCLAuthorizationStatusAuthorizedAlways) { 51 | [self.locationManager startUpdatingLocation]; 52 | } else { 53 | if ([self.locationManager respondsToSelector:@selector(requestWhenInUseAuthorization)]) { 54 | [self.locationManager requestWhenInUseAuthorization]; 55 | } 56 | } 57 | }); 58 | } 59 | 60 | //通用api 61 | RCT_REMAP_METHOD(apiRequest, 62 | postData:(NSDictionary *)parameters 63 | resolver:(RCTPromiseResolveBlock)resolver 64 | rejecter:(RCTPromiseRejectBlock)rejecter) { 65 | 66 | NSString *apiName = [parameters objectForKey:@"apiName"]; 67 | NSDictionary *postData = [parameters objectForKey:@"postData"]; 68 | NSString *version = [parameters objectForKey:@"version"]; 69 | 70 | ThingSmartRequest *request = [ThingSmartRequest new]; 71 | 72 | [request requestWithApiName:apiName postData:postData version:version success:^(id result) { 73 | if ([result isKindOfClass:[NSDictionary class]] || [result isKindOfClass:[NSArray class]]) { 74 | if (resolver) { 75 | resolver([result thingsdk_JSONString]); 76 | } 77 | } else { 78 | if (resolver) { 79 | resolver([result description]); 80 | } 81 | } 82 | } failure:^(NSError *error) { 83 | if (rejecter) { 84 | rejecter([NSString stringWithFormat:@"%ld", error.code], error.userInfo[NSLocalizedDescriptionKey], error); 85 | } 86 | }]; 87 | } 88 | 89 | //判断网络 90 | RCT_EXPORT_METHOD(openNetworkSettings:(NSDictionary *)params) { 91 | 92 | [TuyaRNUtils openNetworkSettings]; 93 | 94 | } 95 | 96 | RCT_EXPORT_METHOD(exitApp:(NSDictionary *)params) { 97 | 98 | } 99 | 100 | RCT_EXPORT_METHOD(onDestory:(NSDictionary *)params) { 101 | 102 | } 103 | 104 | RCT_EXPORT_METHOD(setLocation:(NSDictionary *)params) { 105 | NSString *lat = params[kTuyaCoreModuleParamLat]; 106 | NSString *lon = params[kTuyaCoreModuleParamLon]; 107 | if ([lat isKindOfClass:[NSString class]] && lat.length > 0 108 | && [lon isKindOfClass:[NSString class]] && lon.length > 0) { 109 | [[ThingSmartSDK sharedInstance] setValue:lat forKey:@"latitude"]; 110 | [[ThingSmartSDK sharedInstance] setValue:lon forKey:@"longitude"]; 111 | [self.locationManager stopUpdatingLocation]; 112 | } 113 | } 114 | 115 | RCT_EXPORT_METHOD(getLocationData:(RCTPromiseResolveBlock)resolver 116 | rejecter:(RCTPromiseRejectBlock)rejecter) { 117 | // BOOL gpsAvaliable = [CLLocationManager authorizationStatus] == kCLAuthorizationStatusAuthorizedWhenInUse || [CLLocationManager authorizationStatus] == kCLAuthorizationStatusAuthorizedAlways; 118 | // 119 | NSString *lat = [[NSUserDefaults standardUserDefaults] objectForKey:kTuyaCoreModuleUserDefaultLocation_lat]; 120 | NSString *lon = [[NSUserDefaults standardUserDefaults] objectForKey:kTuyaCoreModuleUserDefaultLocation_lon]; 121 | 122 | if (lat.length == 0) { 123 | lat = @""; 124 | } 125 | if (lon.length == 0) { 126 | lon = @""; 127 | } 128 | 129 | if (resolver) { 130 | resolver(@{ 131 | kTuyaCoreModuleParamLat: [lat isKindOfClass:[NSString class]] ? lat : @"", 132 | kTuyaCoreModuleParamLon: [lat isKindOfClass:[NSString class]] ? lon : @"" 133 | }); 134 | } 135 | } 136 | 137 | 138 | #pragma mark - delegate 139 | #pragma mark - 140 | 141 | - (void)locationManager:(CLLocationManager *)manager 142 | didUpdateLocations:(NSArray *)locations { 143 | if (!([locations isKindOfClass:[NSArray class]] && locations.count > 0)) { 144 | return; 145 | } 146 | CLLocation *location = locations[0]; 147 | 148 | [self.locationManager stopUpdatingLocation]; 149 | 150 | NSString *latitude = [NSString stringWithFormat:@"%f", location.coordinate.latitude]; 151 | NSString *longitude = [NSString stringWithFormat:@"%f", location.coordinate.longitude]; 152 | 153 | [[NSUserDefaults standardUserDefaults] setObject:latitude forKey:kTuyaCoreModuleParamLat]; 154 | [[NSUserDefaults standardUserDefaults] setObject:longitude forKey:kTuyaCoreModuleParamLon]; 155 | [[NSUserDefaults standardUserDefaults] synchronize]; 156 | } 157 | 158 | - (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status { 159 | if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusAuthorizedWhenInUse || [CLLocationManager authorizationStatus] == kCLAuthorizationStatusAuthorizedAlways) { 160 | [self.locationManager startUpdatingLocation]; 161 | } 162 | } 163 | 164 | @end 165 | -------------------------------------------------------------------------------- /android/src/main/java/com/tuya/smart/rnsdk/home/TuyaHomeDataManagerModule.kt: -------------------------------------------------------------------------------- 1 | package com.tuya.smart.rnsdk.home 2 | 3 | import com.facebook.react.bridge.* 4 | import com.thingclips.smart.home.sdk.ThingHomeSdk 5 | import com.tuya.smart.rnsdk.utils.Constant.DEVID 6 | import com.tuya.smart.rnsdk.utils.Constant.GROUPID 7 | import com.tuya.smart.rnsdk.utils.Constant.HOMEID 8 | import com.tuya.smart.rnsdk.utils.Constant.MESHID 9 | import com.tuya.smart.rnsdk.utils.Constant.ROOMID 10 | import com.tuya.smart.rnsdk.utils.JsonUtils 11 | import com.tuya.smart.rnsdk.utils.ReactParamsCheck 12 | import com.tuya.smart.rnsdk.utils.TuyaReactUtils 13 | 14 | 15 | class TuyaHomeDataManagerModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) { 16 | override fun getName(): String { 17 | return "TuyaHomeDataManagerModule" 18 | } 19 | 20 | 21 | /* 家庭下面的房间列表 */ 22 | @ReactMethod 23 | fun getHomeRoomList(params: ReadableMap, promise: Promise) { 24 | promise.resolve(TuyaReactUtils.parseToWritableArray( 25 | JsonUtils.toJsonArray(ThingHomeSdk.getDataInstance().getHomeRoomList(params.getDouble(HOMEID).toLong())))) 26 | } 27 | 28 | 29 | /* 获取家庭下面的设备列表 */ 30 | @ReactMethod 31 | fun getHomeDeviceList(params: ReadableMap, promise: Promise) { 32 | if (ReactParamsCheck.checkParams(arrayOf(HOMEID), params)) { 33 | promise.resolve(TuyaReactUtils.parseToWritableArray( 34 | JsonUtils.toJsonArray(ThingHomeSdk.getDataInstance().getHomeDeviceList(params.getDouble(HOMEID).toLong())))) 35 | } 36 | } 37 | /* 获取家庭下面的群组列表 */ 38 | @ReactMethod 39 | fun getHomeGroupList(params: ReadableMap, promise: Promise) { 40 | if (ReactParamsCheck.checkParams(arrayOf(HOMEID), params)) { 41 | promise.resolve(TuyaReactUtils.parseToWritableArray( 42 | JsonUtils.toJsonArray(ThingHomeSdk.getDataInstance().getHomeGroupList(params.getDouble(HOMEID).toLong())))) 43 | } 44 | } 45 | 46 | /* 获取群组 */ 47 | @ReactMethod 48 | fun getGroupBean(params: ReadableMap, promise: Promise) { 49 | if (ReactParamsCheck.checkParams(arrayOf(GROUPID), params)) { 50 | promise.resolve(TuyaReactUtils.parseToWritableMap(ThingHomeSdk.getDataInstance().getGroupBean(params.getDouble(GROUPID).toLong()))) 51 | } 52 | } 53 | 54 | /* 获取设备 */ 55 | @ReactMethod 56 | fun getDeviceBean(params: ReadableMap, promise: Promise) { 57 | if (ReactParamsCheck.checkParams(arrayOf(DEVID), params)) { 58 | promise.resolve(TuyaReactUtils.parseToWritableMap(ThingHomeSdk.getDataInstance().getDeviceBean(params.getString(DEVID)))) 59 | } 60 | } 61 | 62 | /* 获取设备 */ 63 | @ReactMethod 64 | fun getGroupRoomBean(params: ReadableMap, promise: Promise) { 65 | if (ReactParamsCheck.checkParams(arrayOf(GROUPID), params)) { 66 | promise.resolve(TuyaReactUtils.parseToWritableMap(ThingHomeSdk.getDataInstance().getGroupRoomBean(params.getDouble(GROUPID).toLong()))) 67 | } 68 | } 69 | 70 | /* 获取房间 */ 71 | @ReactMethod 72 | fun getRoomBean(params: ReadableMap, promise: Promise) { 73 | if (ReactParamsCheck.checkParams(arrayOf(ROOMID), params)) { 74 | promise.resolve(TuyaReactUtils.parseToWritableMap(ThingHomeSdk.getDataInstance().getRoomBean(params.getDouble(ROOMID).toLong()))) 75 | } 76 | } 77 | 78 | /* 根据设备获取房间信息 */ 79 | @ReactMethod 80 | fun getDeviceRoomBean(params: ReadableMap, promise: Promise) { 81 | if (ReactParamsCheck.checkParams(arrayOf(DEVID), params)) { 82 | promise.resolve(TuyaReactUtils.parseToWritableMap(ThingHomeSdk.getDataInstance().getDeviceRoomBean(params.getString(DEVID)))) 83 | } 84 | } 85 | 86 | /* 获取群组下面的设备列表 */ 87 | @ReactMethod 88 | fun getGroupDeviceList(params: ReadableMap, promise: Promise) { 89 | if (ReactParamsCheck.checkParams(arrayOf(GROUPID), params)) { 90 | promise.resolve(TuyaReactUtils.parseToWritableArray( 91 | JsonUtils.toJsonArray(ThingHomeSdk.getDataInstance().getGroupDeviceList(params.getDouble(GROUPID).toLong())))) 92 | } 93 | } 94 | 95 | /* 获取mesh下面的群组列表 */ 96 | @ReactMethod 97 | fun getMeshGroupList(params: ReadableMap, promise: Promise) { 98 | if (ReactParamsCheck.checkParams(arrayOf(MESHID), params)) { 99 | promise.resolve(TuyaReactUtils.parseToWritableArray( 100 | JsonUtils.toJsonArray(ThingHomeSdk.getDataInstance().getMeshGroupList(params.getString(MESHID))))) 101 | } 102 | } 103 | 104 | @ReactMethod 105 | fun getMeshDeviceList(params: ReadableMap, promise: Promise) { 106 | if (ReactParamsCheck.checkParams(arrayOf(MESHID), params)) { 107 | promise.resolve(TuyaReactUtils.parseToWritableArray( 108 | JsonUtils.toJsonArray(ThingHomeSdk.getDataInstance().getMeshDeviceList(params.getString(MESHID))))) 109 | } 110 | } 111 | 112 | 113 | /* 根据房间ID获取房间下面的设备列表 */ 114 | @ReactMethod 115 | fun getRoomDeviceList(params: ReadableMap, promise: Promise) { 116 | if (ReactParamsCheck.checkParams(arrayOf(ROOMID), params)) { 117 | promise.resolve(TuyaReactUtils.parseToWritableArray( 118 | JsonUtils.toJsonArray(ThingHomeSdk.getDataInstance().getRoomDeviceList(params.getDouble(ROOMID).toLong())))) 119 | } 120 | } 121 | 122 | 123 | /* 根据房间ID获取房间下面的群组列表 */ 124 | @ReactMethod 125 | fun getRoomGroupList(params: ReadableMap, promise: Promise) { 126 | if (ReactParamsCheck.checkParams(arrayOf(ROOMID), params)) { 127 | promise.resolve(TuyaReactUtils.parseToWritableArray( 128 | JsonUtils.toJsonArray(ThingHomeSdk.getDataInstance().getRoomGroupList(params.getDouble(ROOMID).toLong())))) 129 | } 130 | } 131 | 132 | /* 根据房间ID获取房间下面的群组列表 */ 133 | @ReactMethod 134 | fun getHomeBean(params: ReadableMap, promise: Promise) { 135 | if (ReactParamsCheck.checkParams(arrayOf(HOMEID), params)) { 136 | promise.resolve(TuyaReactUtils.parseToWritableMap(ThingHomeSdk.getDataInstance().getHomeBean(params.getDouble(HOMEID).toLong()))) 137 | } 138 | } 139 | 140 | } 141 | -------------------------------------------------------------------------------- /android/src/main/java/com/tuya/smart/rnsdk/group/TuyaGroupModule.kt: -------------------------------------------------------------------------------- 1 | package com.tuya.smart.rnsdk.group 2 | 3 | import com.facebook.react.bridge.* 4 | import com.thingclips.smart.home.sdk.ThingHomeSdk 5 | import com.thingclips.smart.home.sdk.api.IThingHome 6 | import com.thingclips.smart.home.sdk.callback.IThingResultCallback 7 | import com.thingclips.smart.sdk.api.IGroupListener 8 | import com.thingclips.smart.sdk.api.IThingGroup 9 | import com.thingclips.smart.sdk.bean.GroupDeviceBean 10 | import com.tuya.smart.rnsdk.utils.* 11 | import com.tuya.smart.rnsdk.utils.Constant.COMMAND 12 | import com.tuya.smart.rnsdk.utils.Constant.DEVIDS 13 | import com.tuya.smart.rnsdk.utils.Constant.GROUPID 14 | import com.tuya.smart.rnsdk.utils.Constant.HOMEID 15 | import com.tuya.smart.rnsdk.utils.Constant.NAME 16 | import com.tuya.smart.rnsdk.utils.Constant.PRODUCTID 17 | import com.tuya.smart.rnsdk.utils.Constant.getIResultCallback 18 | 19 | 20 | 21 | 22 | class TuyaGroupModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) { 23 | override fun getName(): String { 24 | return "TuyaGroupModule" 25 | } 26 | 27 | /*创建群组*/ 28 | @ReactMethod 29 | fun createGroup(params: ReadableMap, promise: Promise) { 30 | if (ReactParamsCheck.checkParams(arrayOf(HOMEID, PRODUCTID, NAME, DEVIDS), params)) { 31 | getITuyaHome(params.getDouble(HOMEID).toLong()).createGroup( 32 | params.getString((PRODUCTID)), 33 | params.getString(NAME), 34 | JsonUtils.parserArraybyMap(params.getArray(DEVIDS) as ReadableArray, 35 | String::class.java) as MutableList?, 36 | object : IThingResultCallback { 37 | override fun onSuccess(p0: Long) { 38 | promise.resolve(p0) 39 | } 40 | 41 | override fun onError(p0: String?, p1: String?) { 42 | promise.reject(p0,p1) 43 | } 44 | } 45 | ) 46 | } 47 | } 48 | 49 | /**onNetworkStatusChanged 50 | * 此接口主要是从云端拉取最新群组列表 根据产品ID 51 | */ 52 | @ReactMethod 53 | fun queryDeviceListToAddGroup(params: ReadableMap, promise: Promise) { 54 | if (ReactParamsCheck.checkParams(arrayOf(HOMEID,PRODUCTID), params)) { 55 | getITuyaHome(params.getDouble(HOMEID).toLong()).queryDeviceListToAddGroup(params.getDouble(HOMEID).toLong(),params.getString(PRODUCTID), 56 | object : IThingResultCallback>{ 57 | override fun onSuccess(bizResult: List) { 58 | promise.resolve(TuyaReactUtils.parseToWritableArray(JsonUtils.toJsonArray(bizResult))) 59 | } 60 | 61 | override fun onError(errorCode: String, errorMsg: String) { 62 | promise.reject(errorCode,errorMsg) 63 | } 64 | }) 65 | } 66 | } 67 | 68 | @ReactMethod 69 | fun dismissGroup(params: ReadableMap, promise: Promise) { 70 | if (ReactParamsCheck.checkParams(arrayOf(GROUPID), params)) { 71 | getITuyaGroup(params.getDouble(GROUPID).toLong()) 72 | ?.dismissGroup(getIResultCallback(promise) 73 | ) 74 | } 75 | } 76 | 77 | @ReactMethod 78 | fun updateGroupName(params: ReadableMap, promise: Promise){ 79 | if (ReactParamsCheck.checkParams(arrayOf(GROUPID, NAME), params)) { 80 | getITuyaGroup(params.getDouble(GROUPID).toLong()) 81 | ?.renameGroup( params.getString(NAME) 82 | ,getIResultCallback(promise) 83 | ) 84 | } 85 | } 86 | 87 | @ReactMethod 88 | fun registerGroupListener(params: ReadableMap) { 89 | if (ReactParamsCheck.checkParams(arrayOf(GROUPID), params)) { 90 | getITuyaGroup(params.getDouble(GROUPID).toLong()) 91 | ?.registerGroupListener(object : IGroupListener { 92 | override fun onDpUpdate(var1: Long, var3: String){ 93 | var map=Arguments.createMap(); 94 | map.putDouble("id",var1.toDouble()) 95 | map.putString("dps",var3) 96 | map.putString("type","onDpUpdate") 97 | BridgeUtils.groupListener(reactApplicationContext,map,params.getDouble(GROUPID).toLong()) 98 | } 99 | 100 | override fun onDpCodeUpdate(groupId: Long, dpCodeMap: MutableMap?) { 101 | // 102 | } 103 | 104 | override fun onGroupInfoUpdate(var1: Long){ 105 | var map=Arguments.createMap(); 106 | map.putDouble("id",var1.toDouble()) 107 | map.putString("type","onGroupInfoUpdate") 108 | BridgeUtils.groupListener(reactApplicationContext,map,params.getDouble(GROUPID).toLong()) 109 | } 110 | 111 | override fun onGroupRemoved(var1: Long){ 112 | var map=Arguments.createMap(); 113 | map.putDouble("id",var1.toDouble()) 114 | map.putString("type","onGroupRemoved") 115 | BridgeUtils.groupListener(reactApplicationContext,map,params.getDouble(GROUPID).toLong()) 116 | } 117 | }) 118 | } 119 | } 120 | 121 | @ReactMethod 122 | fun unregisterGroupListener(params: ReadableMap) { 123 | if (ReactParamsCheck.checkParams(arrayOf(GROUPID), params)) { 124 | getITuyaGroup(params.getDouble(GROUPID).toLong()) 125 | ?.unRegisterGroupListener() 126 | } 127 | } 128 | @ReactMethod 129 | fun publishDps(params: ReadableMap,promise: Promise){ 130 | if (ReactParamsCheck.checkParams(arrayOf(GROUPID,COMMAND), params)) { 131 | getITuyaGroup(params.getDouble(GROUPID).toLong()) 132 | ?.publishDps(JsonUtils.toString(TuyaReactUtils.parseToMap(params.getMap(COMMAND) as ReadableMap)), getIResultCallback(promise)) 133 | } 134 | } 135 | 136 | @ReactMethod 137 | fun onDestroy(params: ReadableMap){ 138 | if (ReactParamsCheck.checkParams(arrayOf(GROUPID,COMMAND), params)) { 139 | getITuyaGroup(params.getDouble(GROUPID).toLong()) 140 | ?.onDestroy() 141 | } 142 | } 143 | 144 | fun getITuyaHome(homeId: Long): IThingHome { 145 | return ThingHomeSdk.newHomeInstance(homeId) 146 | } 147 | 148 | fun getITuyaGroup(groupId: Long): IThingGroup { 149 | return ThingHomeSdk.newGroupInstance(groupId) 150 | } 151 | 152 | } 153 | -------------------------------------------------------------------------------- /ios/RNTuyaSdk/DeviceControl/TuyaRNDeviceModule.m: -------------------------------------------------------------------------------- 1 | // 2 | // TuyaRNDeviceModule.m 3 | // TuyaRnDemo 4 | // 5 | // Created by 浩天 on 2019/2/28. 6 | // Copyright © 2019年 Facebook. All rights reserved. 7 | // 8 | 9 | #import "TuyaRNDeviceModule.h" 10 | #import "TuyaRNDeviceListener.h" 11 | #import 12 | #import "TuyaRNUtils.h" 13 | #import "YYModel.h" 14 | 15 | 16 | #define kTuyaDeviceModuleDevId @"devId" 17 | #define kTuyaDeviceModuleCommand @"command" 18 | #define kTuyaDeviceModuleDpId @"dpId" 19 | #define kTuyaDeviceModuleDeviceName @"name" 20 | 21 | @interface TuyaRNDeviceModule() 22 | 23 | @property (strong, nonatomic) ThingSmartDevice *smartDevice; 24 | 25 | @end 26 | 27 | @implementation TuyaRNDeviceModule 28 | 29 | RCT_EXPORT_MODULE(TuyaDeviceModule) 30 | 31 | /** 32 | 设备监听开启 33 | */ 34 | RCT_EXPORT_METHOD(registerDevListener:(NSDictionary *)params resolver:(RCTPromiseResolveBlock)resolver rejecter:(RCTPromiseRejectBlock)rejecter) { 35 | 36 | self.smartDevice = [self smartDeviceWithParams:params]; 37 | //监听设备 38 | [TuyaRNDeviceListener registerDevice:self.smartDevice type:TuyaRNDeviceListenType_DeviceInfo]; 39 | } 40 | 41 | /** 42 | 设备监听删除 43 | 44 | */ 45 | RCT_EXPORT_METHOD(unRegisterDevListener:(NSDictionary *)params resolver:(RCTPromiseResolveBlock)resolver rejecter:(RCTPromiseRejectBlock)rejecter) { 46 | NSString *deviceId = params[kTuyaDeviceModuleDevId]; 47 | if(deviceId.length == 0) { 48 | return; 49 | } 50 | 51 | ThingSmartDevice *device = [ThingSmartDevice deviceWithDeviceId:deviceId]; 52 | 53 | // 移除监听设备 54 | [TuyaRNDeviceListener removeDevice:device type:TuyaRNDeviceListenType_DeviceInfo]; 55 | 56 | self.smartDevice = [self smartDeviceWithParams:params]; 57 | //取消设备监听 58 | [TuyaRNDeviceListener removeDevice:self.smartDevice type:TuyaRNDeviceListenType_DeviceInfo]; 59 | } 60 | 61 | 62 | /* 63 | * 通过局域网或者云端这两种方式发送控制指令给设备。send(通过局域网或者云端这两种方式发送控制指令给设备。) 64 | command的格式应符合{key:value} 例如 {"1":true} 65 | */ 66 | RCT_EXPORT_METHOD(send:(NSDictionary *)params resolver:(RCTPromiseResolveBlock)resolver rejecter:(RCTPromiseRejectBlock)rejecter) { 67 | //设备发送消息 68 | self.smartDevice = [self smartDeviceWithParams:params]; 69 | NSDictionary *command = params[kTuyaDeviceModuleCommand]; 70 | [self.smartDevice publishDps:command success:^{ 71 | [TuyaRNUtils resolverWithHandler:resolver]; 72 | } failure:^(NSError *error) { 73 | [TuyaRNUtils rejecterWithError:error handler:rejecter]; 74 | }]; 75 | } 76 | 77 | /** 78 | 查询单个dp数据 79 | */ 80 | RCT_EXPORT_METHOD(getDp:(NSDictionary *)params resolver:(RCTPromiseResolveBlock)resolver rejecter:(RCTPromiseRejectBlock)rejecter) { 81 | 82 | NSString *dpId = params[kTuyaDeviceModuleDpId]; 83 | //读取dp点 84 | self.smartDevice = [self smartDeviceWithParams:params]; 85 | if (self.smartDevice) { 86 | if (resolver) { 87 | resolver(self.smartDevice.deviceModel.dps[dpId]?:@""); 88 | } 89 | } 90 | } 91 | 92 | 93 | /** 94 | 设备重命名 95 | */ 96 | RCT_EXPORT_METHOD(renameDevice:(NSDictionary *)params resolver:(RCTPromiseResolveBlock)resolver rejecter:(RCTPromiseRejectBlock)rejecter) { 97 | 98 | self.smartDevice = [self smartDeviceWithParams:params]; 99 | NSString *deviceName = params[kTuyaDeviceModuleDeviceName]; 100 | [self.smartDevice updateName:deviceName success:^{ 101 | [TuyaRNUtils resolverWithHandler:resolver]; 102 | } failure:^(NSError *error) { 103 | [TuyaRNUtils rejecterWithError:error handler:rejecter]; 104 | }]; 105 | } 106 | 107 | // 更新单个设备信息: 108 | //RCT_EXPORT_METHOD(getDp:(NSDictionary *)params resolver:(RCTPromiseResolveBlock)resolver rejecter:(RCTPromiseRejectBlock)rejecter) { 109 | // TuyaSmartDevice *device = [TuyaSmartDevice deviceWithDeviceId:params[@"devId"]]; 110 | // [device syncWithCloud:^{ 111 | // if (resolver) { 112 | // resolver(@"syncWithCloud success"); 113 | // } 114 | // } failure:^(NSError *error) { 115 | // [TuyaRNUtils rejecterWithError:error handler:rejecter]; 116 | // }]; 117 | //} 118 | 119 | 120 | RCT_EXPORT_METHOD(getDataPointStat:(NSDictionary *)params resolver:(RCTPromiseResolveBlock)resolver rejecter:(RCTPromiseRejectBlock)rejecter) { 121 | self.smartDevice = [self smartDeviceWithParams:params]; 122 | } 123 | 124 | 125 | /** 126 | 删除设备 127 | */ 128 | RCT_EXPORT_METHOD(removeDevice:(NSDictionary *)params resolver:(RCTPromiseResolveBlock)resolver rejecter:(RCTPromiseRejectBlock)rejecter) { 129 | 130 | self.smartDevice = [self smartDeviceWithParams:params]; 131 | [self.smartDevice remove:^{ 132 | [TuyaRNUtils resolverWithHandler:resolver]; 133 | } failure:^(NSError *error) { 134 | [TuyaRNUtils rejecterWithError:error handler:rejecter]; 135 | }]; 136 | } 137 | 138 | // 设备重命名:已验证 139 | //RCT_EXPORT_METHOD(renameDevice:(NSDictionary *)params resolver:(RCTPromiseResolveBlock)resolver rejecter:(RCTPromiseRejectBlock)rejecter) { 140 | // 141 | // TuyaSmartDevice *device = [TuyaSmartDevice deviceWithDeviceId:params[@"devId"]]; 142 | // [device updateName:params[@"name"] success:^{ 143 | // if (resolver) { 144 | // resolver(@"rename success"); 145 | // } 146 | // } failure:^(NSError *error) { 147 | // [TuyaRNUtils rejecterWithError:error handler:rejecter]; 148 | // }]; 149 | //} 150 | 151 | 152 | RCT_EXPORT_METHOD(onDestroy:(NSDictionary *)params resolver:(RCTPromiseResolveBlock)resolver rejecter:(RCTPromiseRejectBlock)rejecter) { 153 | 154 | } 155 | 156 | // 下发升级指令: 157 | RCT_EXPORT_METHOD(startOta:(NSDictionary *)params resolver:(RCTPromiseResolveBlock)resolver rejecter:(RCTPromiseRejectBlock)rejecter) { 158 | ThingSmartDevice *device = [ThingSmartDevice deviceWithDeviceId:params[@"devId"]]; 159 | [device upgradeFirmware:[params[@"type"] integerValue] success:^{ 160 | if (resolver) { 161 | resolver(@"success"); 162 | } 163 | } failure:^(NSError *error) { 164 | [TuyaRNUtils rejecterWithError:error handler:rejecter]; 165 | }]; 166 | } 167 | 168 | // 查询固件升级信息: 169 | RCT_EXPORT_METHOD(getOtaInfo:(NSDictionary *)params resolver:(RCTPromiseResolveBlock)resolver rejecter:(RCTPromiseRejectBlock)rejecter) { 170 | 171 | ThingSmartDevice *device = [ThingSmartDevice deviceWithDeviceId:params[@"devId"]]; 172 | [device getFirmwareUpgradeInfo:^(NSArray *upgradeModelList) { 173 | 174 | NSMutableArray *res = [NSMutableArray array]; 175 | for (ThingSmartFirmwareUpgradeModel *item in upgradeModelList) { 176 | NSDictionary *dic = [item yy_modelToJSONObject]; 177 | [res addObject:dic]; 178 | } 179 | if (resolver) { 180 | resolver(res); 181 | } 182 | 183 | NSLog(@"getFirmwareUpgradeInfo success"); 184 | } failure:^(NSError *error) { 185 | [TuyaRNUtils rejecterWithError:error handler:rejecter]; 186 | }]; 187 | 188 | } 189 | 190 | 191 | #pragma mark - 192 | - (ThingSmartDevice *)smartDeviceWithParams:(NSDictionary *)params { 193 | NSString *deviceId = params[kTuyaDeviceModuleDevId]; 194 | if(deviceId.length == 0) { 195 | return nil; 196 | } 197 | return [ThingSmartDevice deviceWithDeviceId:deviceId]; 198 | } 199 | 200 | 201 | @end 202 | -------------------------------------------------------------------------------- /ios/RNTuyaSdk/Timer/TuyaRNTimerModule.m: -------------------------------------------------------------------------------- 1 | // 2 | // TuyaRNTimerModule.m 3 | // TuyaRnDemo 4 | // 5 | // Created by 浩天 on 2019/2/28. 6 | // Copyright © 2019年 Facebook. All rights reserved. 7 | // 8 | 9 | #import "TuyaRNTimerModule.h" 10 | #import 11 | #import 12 | #import "TuyaRNUtils.h" 13 | #import 14 | 15 | @interface TuyaRNTimerModule() 16 | @property (nonatomic, strong) ThingSmartTimer *timer; 17 | @end 18 | 19 | @implementation TuyaRNTimerModule 20 | 21 | RCT_EXPORT_MODULE(TuyaTimerModule) 22 | 23 | RCT_EXPORT_METHOD(initWithOptions:(NSDictionary *)params) { 24 | 25 | } 26 | 27 | RCT_EXPORT_METHOD(onDestory:(NSDictionary *)params) { 28 | 29 | } 30 | 31 | // 增加定时器,带有自己定义dp点: 32 | RCT_EXPORT_METHOD(addTimerWithTask:(NSDictionary *)params resolver:(RCTPromiseResolveBlock)resolver rejecter:(RCTPromiseRejectBlock)rejecter) { 33 | ThingSmartTimer *timer = [[ThingSmartTimer alloc] init]; 34 | self.timer = timer; 35 | 36 | [timer addTimerWithTask:params[@"taskName"] loops:params[@"loops"] bizId:params[@"devId"] bizType:0 time:params[@"time"] dps:params[@"dps"] status:YES isAppPush:NO aliasName:@"" success:^{ 37 | if (resolver) { 38 | resolver(@"addTimerWithTask success"); 39 | } 40 | } failure:^(NSError *error) { 41 | [TuyaRNUtils rejecterWithError:error handler:rejecter]; 42 | }]; 43 | } 44 | 45 | 46 | // 获取某设备下的所有定时任务状态: 47 | RCT_EXPORT_METHOD(getTimerTaskStatusWithDeviceId:(NSDictionary *)params resolver:(RCTPromiseResolveBlock)resolver rejecter:(RCTPromiseRejectBlock)rejecter) { 48 | ThingSmartTimer *timer = [[ThingSmartTimer alloc] init]; 49 | self.timer = timer; 50 | [timer getTimerTaskStatusWithDeviceId:params[@"devid"] success:^(NSArray *list) { 51 | 52 | NSMutableArray *res = [NSMutableArray array]; 53 | for (ThingTimerTaskModel *item in list) { 54 | NSDictionary *dic = [item yy_modelToJSONObject]; 55 | [res addObject:dic]; 56 | } 57 | 58 | if (resolver) { 59 | resolver(res); 60 | } 61 | } failure:^(NSError *error) { 62 | [TuyaRNUtils rejecterWithError:error handler:rejecter]; 63 | }]; 64 | } 65 | 66 | // 控制定时任务中所有定时器的开关状态: 67 | RCT_EXPORT_METHOD(updateTimerTaskStatusWithTask:(NSDictionary *)params resolver:(RCTPromiseResolveBlock)resolver rejecter:(RCTPromiseRejectBlock)rejecter) { 68 | ThingSmartTimer *timer = [[ThingSmartTimer alloc] init]; 69 | self.timer = timer; 70 | [timer updateTimerTaskStatusWithTask:params[@"taskName"] bizId:params[@"devId"] bizType:0 updateType:[params[@"status"] integerValue] success:^{ 71 | if (resolver) { 72 | resolver(@"success"); 73 | } 74 | } failure:^(NSError *error) { 75 | [TuyaRNUtils rejecterWithError:error handler:rejecter]; 76 | }]; 77 | } 78 | 79 | // 控制某个定时器的开关状态: 80 | RCT_EXPORT_METHOD(updateTimerStatusWithTask:(NSDictionary *)params resolver:(RCTPromiseResolveBlock)resolver rejecter:(RCTPromiseRejectBlock)rejecter) { 81 | ThingSmartTimer *timer = [[ThingSmartTimer alloc] init]; 82 | self.timer = timer; 83 | 84 | NSInteger status = [params[@"isOpen"] boolValue]?1:0; 85 | 86 | [timer updateTimerStatusWithTask:params[@"taskName"] bizId:params[@"devId"] bizType:0 status:status success:^{ 87 | if (resolver) { 88 | resolver(@"success"); 89 | } 90 | } failure:^(NSError *error) { 91 | [TuyaRNUtils rejecterWithError:error handler:rejecter]; 92 | }]; 93 | } 94 | 95 | // 删除定时器: 96 | RCT_EXPORT_METHOD(removeTimerWithTask:(NSDictionary *)params resolver:(RCTPromiseResolveBlock)resolver rejecter:(RCTPromiseRejectBlock)rejecter) { 97 | ThingSmartTimer *timer = [[ThingSmartTimer alloc] init]; 98 | self.timer = timer; 99 | 100 | [timer removeTimerWithTask:params[@"taskName"] bizId:params[@"devId"] bizType:0 success:^{ 101 | if (resolver) { 102 | resolver(@"success"); 103 | } 104 | } failure:^(NSError *error) { 105 | [TuyaRNUtils rejecterWithError:error handler:rejecter]; 106 | }]; 107 | } 108 | 109 | // 更新定时器的状态: 110 | RCT_EXPORT_METHOD(updateTimerWithTask:(NSDictionary *)params resolver:(RCTPromiseResolveBlock)resolver rejecter:(RCTPromiseRejectBlock)rejecter) { 111 | ThingSmartTimer *timer = [[ThingSmartTimer alloc] init]; 112 | self.timer = timer; 113 | 114 | [timer updateTimerWithTimerId:params[@"timerId"] loops:params[@"loops"] bizId:params[@"devId"] bizType:0 time:params[@"time"] dps:params[@"dps"] status:YES isAppPush:NO aliasName:@"" success:^{ 115 | if (resolver) { 116 | resolver(@"success"); 117 | } 118 | } failure:^(NSError *error) { 119 | [TuyaRNUtils rejecterWithError:error handler:rejecter]; 120 | }]; 121 | } 122 | 123 | // 获取定时任务下所有定时器: 124 | RCT_EXPORT_METHOD(getTimerWithTask:(NSDictionary *)params resolver:(RCTPromiseResolveBlock)resolver rejecter:(RCTPromiseRejectBlock)rejecter) { 125 | ThingSmartTimer *timer = [[ThingSmartTimer alloc] init]; 126 | self.timer = timer; 127 | 128 | [timer getTimerListWithTask:params[@"taskName"] bizId:params[@"devId"] bizType:0 success:^(NSArray *list) { 129 | 130 | NSMutableArray *res = [NSMutableArray array]; 131 | for (ThingTimerModel *item in list) { 132 | NSDictionary *dic = [item yy_modelToJSONObject]; 133 | [res addObject:dic]; 134 | } 135 | 136 | if (resolver) { 137 | resolver(res); 138 | } 139 | } failure:^(NSError *error) { 140 | [TuyaRNUtils rejecterWithError:error handler:rejecter]; 141 | }]; 142 | } 143 | 144 | 145 | // 获取设备所有定时任务下所有定时器: 146 | RCT_EXPORT_METHOD(getAllTimerWithDeviceId:(NSDictionary *)params resolver:(RCTPromiseResolveBlock)resolver rejecter:(RCTPromiseRejectBlock)rejecter) { 147 | ThingSmartTimer *timer = [[ThingSmartTimer alloc] init]; 148 | self.timer = timer; 149 | [timer getAllTimerWithDeviceId:params[@"devId"] success:^(NSDictionary *dict) { 150 | 151 | NSMutableArray *res = [NSMutableArray array]; 152 | 153 | [dict enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, NSArray* _Nonnull obj, BOOL * _Nonnull stop) { 154 | NSMutableArray *arr = [NSMutableArray array]; 155 | 156 | NSMutableDictionary *timerTaskStatus = [NSMutableDictionary dictionary]; 157 | timerTaskStatus[@"timerName"] = key; 158 | NSMutableDictionary *task = [NSMutableDictionary dictionary]; 159 | task[@"timerTaskStatus"] = timerTaskStatus; 160 | 161 | if([obj isKindOfClass:[NSArray class]]) { 162 | for (ThingTimerModel *item in obj) { 163 | NSMutableDictionary *dic = [item yy_modelToJSONObject]; 164 | dic[@"timerId"] = item.timerId; 165 | dic[@"status"] = item.status?@(1):@(0); 166 | task[@"timerTaskStatus"][@"open"] = item.status?@(true):@(false); 167 | [arr addObject:dic]; 168 | } 169 | } 170 | 171 | task[@"timerList"] = arr; 172 | [res addObject:task]; 173 | }]; 174 | if (resolver) { 175 | resolver(res); 176 | } 177 | } failure:^(NSError *error) { 178 | [TuyaRNUtils rejecterWithError:error handler:rejecter]; 179 | }]; 180 | } 181 | 182 | @end 183 | -------------------------------------------------------------------------------- /android/src/main/java/com/tuya/smart/rnsdk/utils/TuyaReactUtils.kt: -------------------------------------------------------------------------------- 1 | package com.tuya.smart.rnsdk.utils 2 | 3 | import android.text.TextUtils 4 | import com.alibaba.fastjson.JSON 5 | import com.alibaba.fastjson.JSONArray 6 | import com.alibaba.fastjson.JSONObject 7 | import com.facebook.react.bridge.* 8 | import com.facebook.react.modules.core.DeviceEventManagerModule 9 | import java.math.BigDecimal 10 | import java.util.ArrayList 11 | import java.util.HashMap 12 | 13 | 14 | object TuyaReactUtils { 15 | /** 16 | * 发送事件给React Native 17 | */ 18 | fun sendEvent(reactContext: ReactContext, eventName: String, params: WritableMap?) { 19 | reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java) 20 | .emit(eventName, params) 21 | } 22 | 23 | fun parseToMap(readableMap: ReadableMap): HashMap { 24 | val iterator = readableMap.keySetIterator() 25 | val deconstructedMap = HashMap() 26 | while (iterator.hasNextKey()) { 27 | val key = iterator.nextKey() 28 | val type = readableMap.getType(key) 29 | when (type) { 30 | ReadableType.Null -> deconstructedMap[key] = null 31 | ReadableType.Boolean -> deconstructedMap[key] = readableMap.getBoolean(key) 32 | ReadableType.Number -> { 33 | val value = readableMap.getDouble(key) 34 | try { 35 | // Long型支持,如果数字大于int, 且是整数,转化成long 36 | if (value > Integer.MAX_VALUE && value % 1 == 0.0) { 37 | deconstructedMap[key] = value.toLong() 38 | } else { 39 | deconstructedMap[key] = value 40 | } 41 | } catch (e: Exception) { 42 | deconstructedMap[key] = value 43 | } 44 | 45 | } 46 | ReadableType.String -> deconstructedMap[key] = readableMap.getString(key) 47 | ReadableType.Map -> deconstructedMap[key] = parseToMap(readableMap.getMap(key) as ReadableMap) 48 | ReadableType.Array -> deconstructedMap[key] = parseToList(readableMap.getArray(key) as ReadableArray) 49 | } 50 | 51 | } 52 | return deconstructedMap 53 | } 54 | 55 | fun parseToLongMap(readableMap: ReadableMap): HashMap { 56 | val iterator = readableMap.keySetIterator() 57 | val deconstructedMap = HashMap() 58 | while (iterator.hasNextKey()) { 59 | val key = iterator.nextKey() 60 | val type = readableMap.getType(key) 61 | when (type) { 62 | ReadableType.Null -> deconstructedMap[key] = null 63 | ReadableType.Boolean -> deconstructedMap[key] = readableMap.getBoolean(key) 64 | ReadableType.Number -> { 65 | val value = readableMap.getDouble(key) 66 | try { 67 | // Long型支持,如果数字大于int, 且是整数,转化成long 68 | if (value > Integer.MAX_VALUE && value % 1 == 0.0) { 69 | deconstructedMap[key] = value.toLong() 70 | } else { 71 | deconstructedMap[key] = value.toLong() 72 | } 73 | } catch (e: Exception) { 74 | deconstructedMap[key] = value 75 | } 76 | 77 | } 78 | ReadableType.String -> deconstructedMap[key] = readableMap.getString(key) 79 | ReadableType.Map -> deconstructedMap[key] = parseToMap(readableMap.getMap(key) as ReadableMap) 80 | ReadableType.Array -> deconstructedMap[key] = parseToList(readableMap.getArray(key) as ReadableArray) 81 | } 82 | 83 | } 84 | return deconstructedMap 85 | } 86 | 87 | fun parseToList(readableArray: ReadableArray): ArrayList { 88 | val deconstructedList = ArrayList(readableArray.size()) 89 | for (i in 0 until readableArray.size()) { 90 | val indexType = readableArray.getType(i) 91 | when (indexType) { 92 | ReadableType.Null -> deconstructedList.add(i, null) 93 | ReadableType.Boolean -> deconstructedList.add(i, readableArray.getBoolean(i)) 94 | ReadableType.Number -> { 95 | val value = readableArray.getDouble(i) 96 | try { 97 | // Long型支持,如果数字大于int, 且是整数,转化成long 98 | if (value > Integer.MAX_VALUE && value % 1 == 0.0) { 99 | deconstructedList.add(i, value.toLong()) 100 | } else { 101 | deconstructedList.add(i, value) 102 | } 103 | } catch (e: Exception) { 104 | deconstructedList.add(i, value) 105 | } 106 | 107 | } 108 | ReadableType.String -> deconstructedList.add(i, readableArray.getString(i)) 109 | ReadableType.Map -> deconstructedList.add(i, parseToMap(readableArray.getMap(i) as ReadableMap)) 110 | ReadableType.Array -> deconstructedList.add(i, parseToList(readableArray.getArray(i) as ReadableArray)) 111 | } 112 | } 113 | return deconstructedList 114 | } 115 | 116 | fun parseToWritableMap(s: String): WritableMap { 117 | return if (TextUtils.isEmpty(s)) Arguments.createMap() else parseToWritableMap(JSON.parseObject(s)) 118 | } 119 | 120 | fun parseToWritableMap(data: Any?): WritableMap { 121 | return if (null == data) Arguments.createMap() else parseToWritableMap(JSON.toJSONString(data)) 122 | } 123 | 124 | fun parseToWritableMap(json: JSONObject): WritableMap { 125 | val map = Arguments.createMap() 126 | val entries = json.entries 127 | for ((key, obv) in entries) { 128 | when (obv) { 129 | is JSONObject -> map.putMap(key, parseToWritableMap(obv)) 130 | is JSONArray -> map.putArray(key, parseToWritableArray(obv)) 131 | is Int -> map.putInt(key, obv) 132 | is String -> map.putString(key, obv) 133 | is Boolean -> map.putBoolean(key, obv) 134 | is Double -> map.putDouble(key, obv) 135 | is BigDecimal -> map.putDouble(key, obv.toDouble()) 136 | is Long ->map.putString(key,obv.toString()) 137 | else -> map.putNull(key) 138 | } 139 | } 140 | return map 141 | } 142 | 143 | fun parseToWritableArray(jsonArray: JSONArray): WritableArray { 144 | val list = Arguments.createArray() 145 | for (obv in jsonArray.toTypedArray()) { 146 | when (obv) { 147 | is JSONObject -> list.pushMap(parseToWritableMap(obv)) 148 | is JSONArray -> list.pushArray(parseToWritableArray(obv)) 149 | is Int -> list.pushInt(obv) 150 | is String -> list.pushString(obv) 151 | is Boolean -> list.pushBoolean(obv) 152 | is Double -> list.pushDouble(obv) 153 | is BigDecimal -> list.pushDouble(obv.toDouble()) 154 | is Long -> list.pushString(obv.toString()) 155 | else -> list.pushNull() 156 | } 157 | } 158 | return list 159 | 160 | } 161 | } 162 | -------------------------------------------------------------------------------- /android/src/main/java/com/tuya/smart/rnsdk/device/TuyaDeviceModule.kt: -------------------------------------------------------------------------------- 1 | package com.tuya.smart.rnsdk.device 2 | 3 | import android.util.Log 4 | import com.alibaba.fastjson.JSONObject 5 | import com.facebook.react.bridge.* 6 | import com.thingclips.smart.android.device.api.IGetDataPointStatCallback 7 | import com.thingclips.smart.android.device.bean.DataPointStatBean 8 | import com.thingclips.smart.android.device.enums.DataPointTypeEnum 9 | import com.thingclips.smart.home.sdk.ThingHomeSdk 10 | import com.thingclips.smart.sdk.api.IDevListener 11 | import com.thingclips.smart.sdk.api.IThingDevice 12 | import com.tuya.smart.rnsdk.utils.BridgeUtils 13 | import com.tuya.smart.rnsdk.utils.Constant.COMMAND 14 | import com.tuya.smart.rnsdk.utils.Constant.DATAPOINTTYPEENUM 15 | import com.tuya.smart.rnsdk.utils.Constant.DEVID 16 | import com.tuya.smart.rnsdk.utils.Constant.DPID 17 | import com.tuya.smart.rnsdk.utils.Constant.NAME 18 | import com.tuya.smart.rnsdk.utils.Constant.NUMBER 19 | import com.tuya.smart.rnsdk.utils.Constant.STARTTIME 20 | import com.tuya.smart.rnsdk.utils.Constant.getIResultCallback 21 | import com.tuya.smart.rnsdk.utils.ReactParamsCheck 22 | import com.tuya.smart.rnsdk.utils.TuyaReactUtils 23 | 24 | 25 | class TuyaDeviceModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) { 26 | 27 | var device: IThingDevice? = null 28 | 29 | override fun getName(): String { 30 | return "TuyaDeviceModule" 31 | } 32 | 33 | @ReactMethod 34 | fun getDevice(params: ReadableMap, promise: Promise) { 35 | if (ReactParamsCheck.checkParams(arrayOf(DEVID), params)) { 36 | promise.resolve(TuyaReactUtils.parseToWritableMap(getDevice(params.getString(DEVID) as String))) 37 | } 38 | } 39 | 40 | @ReactMethod 41 | fun getDeviceData(params: ReadableMap, promise: Promise) { 42 | if (ReactParamsCheck.checkParams(arrayOf(DEVID), params)) { 43 | promise.resolve(TuyaReactUtils.parseToWritableMap(ThingHomeSdk.getDataInstance().getDeviceBean(params.getString(DEVID)))) 44 | } 45 | } 46 | 47 | @ReactMethod 48 | fun registerDevListener(params: ReadableMap) { 49 | if (ReactParamsCheck.checkParams(arrayOf(DEVID), params)) { 50 | device = getDevice(params.getString(DEVID) as String) 51 | device?.registerDevListener(object : IDevListener { 52 | override fun onDpUpdate(devId: String, dpStr: String) { 53 | //dp数据更新:devId 和相应dp数据 54 | val map = Arguments.createMap() 55 | map.putString("devId", devId) 56 | map.putString("dpStr", dpStr) 57 | map.putString("type", "onDpUpdate"); 58 | BridgeUtils.devListener(reactApplicationContext, map, params.getString(DEVID) as String) 59 | } 60 | 61 | override fun onRemoved(devId: String) { 62 | //设备被移除 63 | val map = Arguments.createMap() 64 | map.putString("devId", devId) 65 | map.putString("type", "onRemoved"); 66 | BridgeUtils.devListener(reactApplicationContext, map, params.getString(DEVID) as String) 67 | } 68 | 69 | override fun onStatusChanged(devId: String, online: Boolean) { 70 | //设备在线状态,online 71 | val map = Arguments.createMap() 72 | map.putString("devId", devId) 73 | map.putBoolean("online", online) 74 | map.putString("type", "onStatusChanged"); 75 | BridgeUtils.devListener(reactApplicationContext, map, params.getString(DEVID) as String) 76 | } 77 | 78 | override fun onNetworkStatusChanged(devId: String, status: Boolean) { 79 | //网络状态监听 80 | val map = Arguments.createMap() 81 | map.putString("devId", devId) 82 | map.putBoolean("status", status) 83 | map.putString("type", "onNetworkStatusChanged"); 84 | 85 | BridgeUtils.devListener(reactApplicationContext, map, params.getString(DEVID) as String) 86 | } 87 | 88 | override fun onDevInfoUpdate(devId: String) { 89 | //设备信息变更,目前只有设备名称变化,会调用该接口 90 | val map = Arguments.createMap() 91 | map.putString("devId", devId) 92 | map.putString("type", "onDevInfoUpdate"); 93 | BridgeUtils.devListener(reactApplicationContext, map, params.getString(DEVID) as String) 94 | } 95 | }) 96 | 97 | } 98 | } 99 | 100 | @ReactMethod 101 | fun unRegisterDevListener(params: ReadableMap) { 102 | if (ReactParamsCheck.checkParams(arrayOf(DEVID), params)) { 103 | if (device != null) { 104 | device!!.unRegisterDevListener() 105 | } 106 | } 107 | } 108 | 109 | @ReactMethod 110 | fun onDestroy(params: ReadableMap) { 111 | if (ReactParamsCheck.checkParams(arrayOf(DEVID), params)) { 112 | getDevice(params.getString(DEVID) as String)?.onDestroy() 113 | } 114 | } 115 | 116 | 117 | @ReactMethod 118 | fun send(params: ReadableMap, promise: Promise) { 119 | if (ReactParamsCheck.checkParams(arrayOf(DEVID, COMMAND), params)) { 120 | getDevice(params.getString(DEVID) as String)?.publishDps(JSONObject.toJSONString(TuyaReactUtils.parseToMap(params.getMap(COMMAND) as ReadableMap)) 121 | , getIResultCallback(promise)) 122 | } 123 | } 124 | 125 | 126 | @ReactMethod 127 | fun getDp(params: ReadableMap, promise: Promise) { 128 | if (ReactParamsCheck.checkParams(arrayOf(DEVID, DPID), params)) { 129 | promise.resolve(getDevice(params.getString(DEVID) as String)?.getDp( 130 | params.getString(DPID), 131 | getIResultCallback(promise) 132 | )) 133 | } 134 | } 135 | 136 | @ReactMethod 137 | fun renameDevice(params: ReadableMap, promise: Promise) { 138 | if (ReactParamsCheck.checkParams(arrayOf(DEVID, NAME), params)) { 139 | getDevice(params.getString(DEVID) as String)?.renameDevice(params.getString(NAME), getIResultCallback(promise)) 140 | } 141 | } 142 | 143 | @ReactMethod 144 | fun getDataPointStat(params: ReadableMap, promise: Promise) { 145 | if (ReactParamsCheck.checkParams(arrayOf(DEVID, DATAPOINTTYPEENUM, NUMBER, DPID, STARTTIME), params)) { 146 | getDevice(params.getString(DEVID) as String)?.getDataPointStat(DataPointTypeEnum.valueOf(params.getString(DATAPOINTTYPEENUM) as String), 147 | params.getDouble(STARTTIME).toLong(), 148 | params.getInt(NUMBER), 149 | params.getString(DPID), 150 | getIGetDataPointStatCallback(promise) 151 | ) 152 | } 153 | } 154 | 155 | @ReactMethod 156 | fun removeDevice(params: ReadableMap, promise: Promise) { 157 | if (ReactParamsCheck.checkParams(arrayOf(DEVID), params)) { 158 | getDevice(params.getString(DEVID) as String)?.removeDevice(getIResultCallback(promise)) 159 | } 160 | } 161 | 162 | fun getIGetDataPointStatCallback(promise: Promise): IGetDataPointStatCallback { 163 | return object : IGetDataPointStatCallback { 164 | 165 | override fun onSuccess(p0: DataPointStatBean?) { 166 | promise.resolve(TuyaReactUtils.parseToWritableMap(p0)) 167 | } 168 | 169 | 170 | override fun onError(code: String?, error: String?) { 171 | promise.reject(code, error) 172 | } 173 | } 174 | } 175 | 176 | 177 | fun getDevice(devId: String): IThingDevice { 178 | return ThingHomeSdk.newDeviceInstance(devId); 179 | } 180 | 181 | } 182 | -------------------------------------------------------------------------------- /ios/RNTuyaSdk/Utils/Listener/TuyaRNHomeListener.m: -------------------------------------------------------------------------------- 1 | // 2 | // TuyaRNHomeListener.m 3 | // TuyaRnDemo 4 | // 5 | // Created by 浩天 on 2019/3/6. 6 | // Copyright © 2019年 Facebook. All rights reserved. 7 | // 8 | 9 | #import "TuyaRNHomeListener.h" 10 | #import 11 | #import 12 | #import "TuyaRNEventEmitter.h" 13 | #import 14 | #import 15 | #import 16 | 17 | @interface TuyaRNHomeListener() 18 | 19 | @property (strong, nonatomic) ThingSmartHome *homeChangeSmartHome; 20 | @property (strong, nonatomic) ThingSmartHome *homeStatusSmartHome; 21 | 22 | @end 23 | 24 | @implementation TuyaRNHomeListener 25 | 26 | + (instancetype)shareInstance { 27 | static TuyaRNHomeListener *_instance = nil; 28 | static dispatch_once_t onceToken; 29 | dispatch_once(&onceToken, ^{ 30 | _instance = [[TuyaRNHomeListener alloc] init]; 31 | }); 32 | return _instance; 33 | } 34 | 35 | - (void)registerHomeChangeWithSmartHome:(ThingSmartHome *)smartHome { 36 | 37 | if (!smartHome) { 38 | return; 39 | } 40 | [TuyaRNHomeListener shareInstance].homeChangeSmartHome = smartHome; 41 | [TuyaRNHomeListener shareInstance].homeChangeSmartHome.delegate = self; 42 | } 43 | 44 | - (void)removeHomeChangeSmartHome { 45 | 46 | [TuyaRNHomeListener shareInstance].homeChangeSmartHome = nil; 47 | [TuyaRNHomeListener shareInstance].homeChangeSmartHome.delegate = nil; 48 | 49 | } 50 | 51 | - (void)registerHomeStatusWithSmartHome:(ThingSmartHome *)smartHome { 52 | 53 | if (!smartHome) { 54 | return; 55 | } 56 | [TuyaRNHomeListener shareInstance].homeStatusSmartHome = smartHome; 57 | [TuyaRNHomeListener shareInstance].homeStatusSmartHome.delegate = self; 58 | } 59 | 60 | - (void)removeHomeStatusSmartHome { 61 | 62 | [TuyaRNHomeListener shareInstance].homeStatusSmartHome = nil; 63 | [TuyaRNHomeListener shareInstance].homeStatusSmartHome.delegate = nil; 64 | 65 | } 66 | 67 | 68 | #pragma mark - ThingSmartHomeDelegate 69 | 70 | // 家庭的信息更新,例如name 71 | - (void)homeDidUpdateInfo:(ThingSmartHome *)home { 72 | 73 | if (!self.homeChangeSmartHome) { 74 | return; 75 | } 76 | 77 | if (home.homeModel.homeId <= 0) { 78 | return; 79 | } 80 | NSDictionary *dic = @{ 81 | @"homeId": [NSNumber numberWithLongLong:home.homeModel.homeId], 82 | @"type": @"onHomeInfoChanged" 83 | }; 84 | [TuyaRNEventEmitter ty_sendEvent:[kTYEventEmitterHomeChangeEvent stringByAppendingString:@"//"] withBody:dic]; 85 | } 86 | 87 | // 我收到的共享设备列表变化 88 | - (void)homeDidUpdateSharedInfo:(ThingSmartHome *)home { 89 | 90 | if (!self.homeChangeSmartHome) { 91 | return; 92 | } 93 | 94 | if (home.homeModel.homeId <= 0) { 95 | return; 96 | } 97 | NSDictionary *dic = @{ 98 | @"homeId": [NSNumber numberWithLongLong:home.homeModel.homeId], 99 | @"type": @"onSharedDeviceList" 100 | }; 101 | [TuyaRNEventEmitter ty_sendEvent:[kTYEventEmitterHomeChangeEvent stringByAppendingString:@"//"] withBody:dic]; 102 | } 103 | 104 | // 房间信息变更,例如name 105 | - (void)home:(ThingSmartHome *)home roomInfoUpdate:(ThingSmartRoomModel *)room { 106 | 107 | if (!self.homeChangeSmartHome) { 108 | return; 109 | } 110 | 111 | //房间的名字的变更 112 | if (home.homeModel.homeId <= 0) { 113 | return; 114 | } 115 | NSDictionary *dic = @{ 116 | @"homeId": [NSNumber numberWithLongLong:home.homeModel.homeId], 117 | @"roomId": [NSNumber numberWithLongLong:room.roomId], 118 | @"type": @"onHomeRoomInfo" 119 | }; 120 | [TuyaRNEventEmitter ty_sendEvent:[kTYEventEmitterHomeChangeEvent stringByAppendingFormat:@"//%lld",home.homeModel.homeId] withBody:dic]; 121 | } 122 | 123 | // 房间与设备,群组的关系变化 124 | - (void)home:(ThingSmartHome *)home roomRelationUpdate:(ThingSmartRoomModel *)room { 125 | 126 | } 127 | 128 | // 添加设备 129 | - (void)home:(ThingSmartHome *)home didAddDeivice:(ThingSmartDeviceModel *)device { 130 | 131 | if (!self.homeStatusSmartHome) { 132 | return; 133 | } 134 | 135 | NSDictionary *dic = @{ 136 | @"homeId": [NSNumber numberWithLongLong:home.homeModel.homeId], 137 | @"devId": device.devId, 138 | @"type": @"onDeviceAdded" 139 | }; 140 | [TuyaRNEventEmitter ty_sendEvent:[kTYEventEmitterHomeStatusEvent stringByAppendingFormat:@"//%lld",home.homeModel.homeId] withBody:dic]; 141 | 142 | } 143 | 144 | // 删除设备 145 | - (void)home:(ThingSmartHome *)home didRemoveDeivice:(NSString *)devId { 146 | 147 | if (!self.homeStatusSmartHome) { 148 | return; 149 | } 150 | NSDictionary *dic = @{ 151 | @"homeId": [NSNumber numberWithLongLong:home.homeModel.homeId], 152 | @"devId": devId, 153 | @"type": @"onDeviceRemoved" 154 | }; 155 | [TuyaRNEventEmitter ty_sendEvent:[kTYEventEmitterHomeStatusEvent stringByAppendingFormat:@"//%lld",home.homeModel.homeId] withBody:dic]; 156 | 157 | } 158 | 159 | // 设备信息更新,例如name 160 | - (void)home:(ThingSmartHome *)home deviceInfoUpdate:(ThingSmartDeviceModel *)device { 161 | 162 | } 163 | 164 | // 设备dp数据更新 165 | - (void)home:(ThingSmartHome *)home device:(ThingSmartDeviceModel *)device dpsUpdate:(NSDictionary *)dps { 166 | 167 | } 168 | 169 | // 添加群组 170 | - (void)home:(ThingSmartHome *)home didAddGroup:(ThingSmartGroupModel *)group { 171 | if (!self.homeStatusSmartHome) { 172 | return; 173 | } 174 | NSDictionary *dic = @{ 175 | @"homeId": [NSNumber numberWithLongLong:home.homeModel.homeId], 176 | @"devId": group.groupId, 177 | @"type": @"onGroupAdded" 178 | }; 179 | [TuyaRNEventEmitter ty_sendEvent:[kTYEventEmitterHomeStatusEvent stringByAppendingFormat:@"//%lld",home.homeModel.homeId] withBody:dic]; 180 | } 181 | 182 | // 群组dp数据更新 183 | - (void)home:(ThingSmartHome *)home group:(ThingSmartGroupModel *)group dpsUpdate:(NSDictionary *)dps { 184 | if (!self.homeStatusSmartHome || !dps || dps.count == 0) { 185 | return; 186 | } 187 | NSDictionary *dic = @{ 188 | @"homeId": [NSNumber numberWithLongLong:home.homeModel.homeId], 189 | @"groupId": group, 190 | @"dps":dps, 191 | @"type": @"onGroupDpsUpdate" 192 | }; 193 | [TuyaRNEventEmitter ty_sendEvent:[kTYEventEmitterHomeStatusEvent stringByAppendingFormat:@"//%lld",home.homeModel.homeId] withBody:dic]; 194 | } 195 | 196 | // 删除群组 197 | - (void)home:(ThingSmartHome *)home didRemoveGroup:(NSString *)groupId { 198 | if (!self.homeStatusSmartHome) { 199 | return; 200 | } 201 | NSDictionary *dic = @{ 202 | @"homeId": [NSNumber numberWithLongLong:home.homeModel.homeId], 203 | @"groupId": groupId, 204 | @"type": @"onGroupRemoved" 205 | }; 206 | [TuyaRNEventEmitter ty_sendEvent:[kTYEventEmitterHomeStatusEvent stringByAppendingFormat:@"//%lld",home.homeModel.homeId] withBody:dic]; 207 | } 208 | 209 | // 群组信息更新,例如name 210 | - (void)home:(ThingSmartHome *)home groupInfoUpdate:(ThingSmartGroupModel *)group { 211 | if (!self.homeStatusSmartHome) { 212 | return; 213 | } 214 | NSDictionary *dic = @{ 215 | @"homeId": [NSNumber numberWithLongLong:home.homeModel.homeId], 216 | @"groupId": group.groupId, 217 | @"type": @"onGroupInfoUpdate" 218 | }; 219 | [TuyaRNEventEmitter ty_sendEvent:[kTYEventEmitterHomeStatusEvent stringByAppendingFormat:@"//%lld",home.homeModel.homeId] withBody:dic]; 220 | } 221 | 222 | @end 223 | -------------------------------------------------------------------------------- /android/src/main/java/com/tuya/smart/rnsdk/timer/TuyaTimerModule.kt: -------------------------------------------------------------------------------- 1 | package com.tuya.smart.rnsdk.timer 2 | 3 | import com.facebook.react.bridge.* 4 | import com.thingclips.smart.home.sdk.ThingHomeSdk 5 | import com.thingclips.smart.sdk.api.IGetAllTimerWithDevIdCallback 6 | import com.thingclips.smart.sdk.api.IGetDeviceTimerStatusCallback 7 | import com.thingclips.smart.sdk.api.IGetTimerWithTaskCallback 8 | import com.thingclips.smart.sdk.api.IResultStatusCallback 9 | import com.thingclips.smart.sdk.bean.TimerTask 10 | import com.thingclips.smart.sdk.bean.TimerTaskStatus 11 | import com.tuya.smart.rnsdk.utils.Constant 12 | import com.tuya.smart.rnsdk.utils.Constant.DEVID 13 | import com.tuya.smart.rnsdk.utils.Constant.DPS 14 | import com.tuya.smart.rnsdk.utils.Constant.ISOPEN 15 | import com.tuya.smart.rnsdk.utils.Constant.LOOPS 16 | import com.tuya.smart.rnsdk.utils.Constant.STATUS 17 | import com.tuya.smart.rnsdk.utils.Constant.TASKNAME 18 | import com.tuya.smart.rnsdk.utils.Constant.TIME 19 | import com.tuya.smart.rnsdk.utils.Constant.TIMERID 20 | import com.tuya.smart.rnsdk.utils.JsonUtils 21 | import com.tuya.smart.rnsdk.utils.ReactParamsCheck 22 | import com.tuya.smart.rnsdk.utils.TuyaReactUtils 23 | import java.util.ArrayList 24 | 25 | 26 | class TuyaTimerModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) { 27 | 28 | override fun getName(): String { 29 | return "TuyaTimerModule" 30 | } 31 | 32 | /** 33 | * 增加定时器 单dp点 默认置为true 支持子设备 34 | * @param taskName 定时任务名称 35 | * @param loops 循环次数 "0000000", 每一位 0:关闭,1:开启, 从左至右依次表示: 周日 周一 周二 周三 周四 周五 周六 36 | * @param devId 设备Id或群组Id 37 | * @param dps dp点键值对,key是dpId,value是dpValue,仅支持单dp点 38 | * @param time 定时任务下的定时钟 39 | * @param callback 回调 40 | */ 41 | @ReactMethod 42 | fun addTimerWithTask(params: ReadableMap,promise: Promise) { 43 | if (ReactParamsCheck.checkParams(arrayOf(TASKNAME, LOOPS,DEVID, DPS, TIME), params)) { 44 | ThingHomeSdk.getTimerManagerInstance().addTimerWithTask( 45 | params.getString(TASKNAME), 46 | params.getString(DEVID), 47 | params.getString(LOOPS), 48 | TuyaReactUtils.parseToMap(params.getMap(DPS) as ReadableMap), 49 | params.getString(TIME), 50 | getIResultStatusCallback(promise) 51 | ) 52 | } 53 | } 54 | 55 | /*获取某设备下的所有定时任务状态*/ 56 | @ReactMethod 57 | fun getTimerTaskStatusWithDeviceId(params: ReadableMap,promise: Promise) { 58 | if (ReactParamsCheck.checkParams(arrayOf(DEVID), params)) { 59 | ThingHomeSdk.getTimerManagerInstance().getTimerTaskStatusWithDeviceId( 60 | params.getString(DEVID), 61 | getIGetDeviceTimerStatusCallback(promise) 62 | ) 63 | } 64 | } 65 | 66 | /*控制定时任务中所有定时器的开关状态*/ 67 | @ReactMethod 68 | fun updateTimerTaskStatusWithTask(params: ReadableMap,promise: Promise) { 69 | if (ReactParamsCheck.checkParams(arrayOf(TASKNAME,DEVID,STATUS), params)) { 70 | ThingHomeSdk.getTimerManagerInstance().updateTimerTaskStatusWithTask( 71 | params.getString(TASKNAME), 72 | params.getString(DEVID), 73 | params.getInt(STATUS), 74 | getIResultStatusCallback(promise) 75 | ) 76 | } 77 | } 78 | 79 | /*控制某个定时器的开关状态*/ 80 | @ReactMethod 81 | fun updateTimerStatusWithTask(params: ReadableMap,promise: Promise) { 82 | if (ReactParamsCheck.checkParams(arrayOf(TASKNAME,DEVID,TIMERID, ISOPEN), params)) { 83 | ThingHomeSdk.getTimerManagerInstance().updateTimerStatusWithTask( 84 | params.getString(TASKNAME), 85 | params.getString(DEVID), 86 | params.getString(TIMERID), 87 | params.getBoolean(ISOPEN), 88 | getIResultStatusCallback(promise) 89 | ) 90 | } 91 | } 92 | 93 | 94 | /*删除定时器*/ 95 | @ReactMethod 96 | fun removeTimerWithTask(params: ReadableMap,promise: Promise) { 97 | if (ReactParamsCheck.checkParams(arrayOf(TASKNAME,DEVID, TIMERID), params)) { 98 | ThingHomeSdk.getTimerManagerInstance().removeTimerWithTask( 99 | params.getString(TASKNAME), 100 | params.getString(DEVID), 101 | params.getString(TIMERID), 102 | getIResultStatusCallback(promise) 103 | ) 104 | } 105 | } 106 | 107 | /** 108 | * * 更新定时器的状态 109 | * @param taskName 定时任务名称 110 | * @param loops 循环次数 如每周每天传”1111111” 111 | * @param devId 设备Id或群组Id 112 | * @param timerId 定时钟Id 113 | * @param time 定时时间 114 | * @param isOpen 是否开启 115 | * @param callback 回调 116 | */ 117 | @ReactMethod 118 | fun updateTimerWithTask(params: ReadableMap,promise: Promise) { 119 | if (ReactParamsCheck.checkParams(arrayOf(TASKNAME, LOOPS, DEVID, TIMERID, TIME, ISOPEN), params)) { 120 | ThingHomeSdk.getTimerManagerInstance().updateTimerWithTask( 121 | params.getString(TASKNAME), 122 | params.getString(LOOPS), 123 | params.getString(DEVID), 124 | params.getString(TIMERID), 125 | // Unfortunately we cannot update dps values, we can only give a single dp id but we also want to control the dp value 126 | null, 127 | params.getString(TIME), 128 | params.getBoolean(ISOPEN), 129 | getIResultStatusCallback(promise)) 130 | } 131 | } 132 | 133 | /*获取定时任务下所有定时器*/ 134 | @ReactMethod 135 | fun getTimerWithTask(params: ReadableMap,promise: Promise) { 136 | if (ReactParamsCheck.checkParams(arrayOf(TASKNAME, DEVID), params)) { 137 | ThingHomeSdk.getTimerManagerInstance().getTimerWithTask( 138 | params.getString(TASKNAME), 139 | params.getString(DEVID), 140 | getIGetTimerWithTaskCallback(promise)) 141 | } 142 | } 143 | 144 | /*获取设备所有定时任务下所有定时器*/ 145 | @ReactMethod 146 | fun getAllTimerWithDeviceId(params: ReadableMap,promise: Promise) { 147 | if (ReactParamsCheck.checkParams(arrayOf(DEVID), params)) { 148 | ThingHomeSdk.getTimerManagerInstance().getAllTimerWithDeviceId( 149 | params.getString(DEVID), 150 | getIGetAllTimerWithDevIdCallback(promise)) 151 | } 152 | } 153 | 154 | fun getIGetAllTimerWithDevIdCallback(promise: Promise): IGetAllTimerWithDevIdCallback { 155 | return object : IGetAllTimerWithDevIdCallback { 156 | override fun onSuccess(p0: ArrayList?) { 157 | promise.resolve(TuyaReactUtils.parseToWritableArray(JsonUtils.toJsonArray(p0!!))) 158 | } 159 | 160 | override fun onError(code: String?, error: String?) { 161 | promise.reject(code, error) 162 | } 163 | } 164 | } 165 | fun getIGetTimerWithTaskCallback(promise: Promise): IGetTimerWithTaskCallback { 166 | return object : IGetTimerWithTaskCallback { 167 | override fun onSuccess(p0: TimerTask?) { 168 | promise.resolve(TuyaReactUtils.parseToWritableMap(p0)) 169 | } 170 | 171 | override fun onError(code: String?, error: String?) { 172 | promise.reject(code, error) 173 | } 174 | } 175 | } 176 | fun getIGetDeviceTimerStatusCallback(promise: Promise): IGetDeviceTimerStatusCallback { 177 | return object : IGetDeviceTimerStatusCallback { 178 | override fun onSuccess(p0: ArrayList?) { 179 | promise.resolve(TuyaReactUtils.parseToWritableArray(JsonUtils.toJsonArray(p0!!))) 180 | } 181 | 182 | override fun onError(code: String?, error: String?) { 183 | promise.reject(code, error) 184 | } 185 | } 186 | } 187 | 188 | fun getIResultStatusCallback(promise: Promise): IResultStatusCallback { 189 | return object : IResultStatusCallback { 190 | override fun onSuccess() { 191 | promise.resolve(Constant.SUCCESS) 192 | } 193 | 194 | override fun onError(code: String?, error: String?) { 195 | promise.reject(code, error) 196 | } 197 | } 198 | } 199 | } 200 | --------------------------------------------------------------------------------