10 |
11 | @interface ESP_NetUtil : NSObject
12 |
13 | /**
14 | * get local ip v4 or nil
15 | *
16 | * @return local ip v4 or nil
17 | */
18 | + (NSString *) getLocalIPv4;
19 |
20 | /**
21 | * get local ip v6 or nil
22 | *
23 | * @return local ip v6 or nil
24 | */
25 | + (NSString *) getLocalIPv6;
26 |
27 | /**
28 | * whether the ipAddr is v4
29 | *
30 | * @return whether the ipAddr is v4
31 | */
32 | + (BOOL) isIPv4Addr:(NSString *)ipAddr;
33 |
34 | /**
35 | * whether the ipAddr v4 is private
36 | *
37 | * @return whether the ipAddr v4 is private
38 | */
39 | + (BOOL) isIPv4PrivateAddr:(NSString *)ipAddr;
40 |
41 | /**
42 | * get the local ip address by local inetAddress ip4
43 | *
44 | * @param localInetAddr4 local inetAddress ip4
45 | */
46 | + (NSData *) getLocalInetAddress4ByAddr:(NSString *) localInetAddr4;
47 |
48 | /**
49 | * get the invented local ip address by local port
50 | *
51 | */
52 | + (NSData *) getLocalInetAddress6ByPort:(int) localPort;
53 |
54 | /**
55 | * parse InetAddress
56 | */
57 | + (NSData *) parseInetAddrByData: (NSData *) inetAddrData andOffset: (int) offset andCount: (int) count;
58 |
59 | /**
60 | * descrpion inetAddrData for print pretty IPv4
61 | */
62 | + (NSString *) descriptionInetAddr4ByData: (NSData *) inetAddrData;
63 |
64 | /**
65 | * descrpion inetAddrData for print pretty IPv6
66 | */
67 | + (NSString *) descriptionInetAddr6ByData: (NSData *) inetAddrData;
68 |
69 | /**
70 | * parse bssid
71 | *
72 | * @param bssid the bssid
73 | * @return byte converted from bssid
74 | */
75 | + (NSData *) parseBssid2bytes: (NSString *) bssid;
76 |
77 | /**
78 | * send a dummy GET to "https://8.8.8.8" just to get Network Permission after ios10.0(including)
79 | */
80 | + (void) tryOpenNetworkPermission;
81 |
82 | @end
83 |
--------------------------------------------------------------------------------
/example/src/App.js:
--------------------------------------------------------------------------------
1 | import SmartConfig from 'react-native-smartconfig-quan';
2 | import { Button, Text, View } from 'react-native';
3 | import React, { useState } from 'react';
4 |
5 | export default function App() {
6 |
7 | const [log, setLog] = useState('log here');
8 | let foundDevice = false;
9 |
10 | const wifiName = 'Viettel';
11 | const wifiPass = '0965677826';
12 | // you can random bssid of wifi, but it need correct format
13 | const wifiBssid = '8a:29:9c:69:af:9b';
14 |
15 | // timeout not work with android, on android default is 45s
16 | const TIME_OUT_SMART_CONFIG = 30 * 1000; // 30s
17 |
18 | function config() {
19 | setLog('configuring...');
20 | foundDevice = false;
21 |
22 | SmartConfig.start(wifiName, wifiBssid, wifiPass, TIME_OUT_SMART_CONFIG, (event) => {
23 | console.log(event);
24 | let { eventName, data } = event;
25 | if (eventName === 'onFoundDevice') {
26 | foundDevice = true;
27 | data = JSON.parse(data);
28 |
29 | // data in event is ip of ESP
30 | setLog('Found device\nip: ' + data.ip + '\nbssid: ' + data.bssid);
31 | } else {
32 | if (!foundDevice) {
33 | setLog('Not found');
34 | }
35 | }
36 | });
37 | }
38 |
39 | function stopConfig() {
40 | SmartConfig.stop();
41 | setLog('Stopped config');
42 | }
43 |
44 | return (
45 |
46 | {log}
47 |
48 |
49 | config()} />
50 |
51 |
52 |
53 | stopConfig()} />
54 |
55 |
56 |
57 | );
58 | }
59 |
--------------------------------------------------------------------------------
/ios/EspTouch/protocol/ESPTouchGenerator.m:
--------------------------------------------------------------------------------
1 | //
2 | // ESPTouchGenerator.m
3 | // EspTouchDemo
4 | //
5 | // Created by fby on 4/9/15.
6 | // Copyright (c) 2015 fby. All rights reserved.
7 | //
8 |
9 | #import "ESPTouchGenerator.h"
10 | #import "ESP_ByteUtil.h"
11 | #import "ESPGuideCode.h"
12 | #import "ESPDatumCode.h"
13 |
14 |
15 | @implementation ESPTouchGenerator
16 |
17 | - (id) initWithSsid: (NSData *)apSsid andApBssid: (NSData *)apBssid andApPassword: (NSData *)apPwd andInetAddrData: (NSData *)ipAddrData andIsSsidHidden:(BOOL) isSsidHidden
18 | {
19 | self = [super init];
20 | if (self)
21 | {
22 | // generate guide code
23 | ESPGuideCode *gc = [[ESPGuideCode alloc]init];
24 | NSData *gcData1 = [gc getU16s];
25 | NSUInteger gcData1Len = [gcData1 length];
26 | UInt16 gcU16_1[gcData1Len/2];
27 | [gcData1 getBytes:gcU16_1 length:gcData1Len];
28 | _gcBytes2 = [[NSMutableArray alloc]initWithCapacity:gcData1Len];
29 | for (int i = 0; i < gcData1Len/2; i++)
30 | {
31 | NSData* data = [ESP_ByteUtil genSpecBytesWithU16:gcU16_1[i]];
32 | [_gcBytes2 addObject:data];
33 | }
34 |
35 | // generate data code
36 | ESPDatumCode *dc = [[ESPDatumCode alloc]initWithSsid:apSsid andApBssid:apBssid andApPwd:apPwd andInetAddrData:ipAddrData andIsSsidHidden:isSsidHidden];
37 | NSData *dcData1 = [dc getU16s];
38 | NSUInteger dcDataLen = [dcData1 length];
39 | UInt16 dcU16_1[dcDataLen/2];
40 | [dcData1 getBytes:dcU16_1 length:dcDataLen];
41 | _dcBytes2 = [[NSMutableArray alloc]initWithCapacity:dcDataLen];
42 | for (int i = 0; i < dcDataLen/2; i++)
43 | {
44 | NSData* data = [ESP_ByteUtil genSpecBytesWithU16:dcU16_1[i]];
45 | [_dcBytes2 addObject:data];
46 | }
47 | }
48 | return self;
49 | }
50 |
51 | - (NSArray *) getGCBytes2
52 | {
53 | return _gcBytes2;
54 | }
55 |
56 | - (NSArray *) getDCBytes2
57 | {
58 | return _dcBytes2;
59 | }
60 | @end
61 |
--------------------------------------------------------------------------------
/android/src/main/java/esptouch/IEsptouchTask.java:
--------------------------------------------------------------------------------
1 | package esptouch;
2 |
3 | import java.util.List;
4 |
5 | public interface IEsptouchTask {
6 | String ESPTOUCH_VERSION = "v0.3.7.1";
7 |
8 | /**
9 | * set the esptouch listener, when one device is connected to the Ap, it will be called back
10 | *
11 | * @param esptouchListener when one device is connected to the Ap, it will be called back
12 | */
13 | void setEsptouchListener(IEsptouchListener esptouchListener);
14 |
15 | /**
16 | * Interrupt the Esptouch Task when User tap back or close the Application.
17 | */
18 | void interrupt();
19 |
20 | /**
21 | * Note: !!!Don't call the task at UI Main Thread or RuntimeException will
22 | * be thrown Execute the Esptouch Task and return the result
23 | *
24 | * Smart Config v2.4 support the API
25 | *
26 | * @return the IEsptouchResult
27 | * @throws RuntimeException
28 | */
29 | IEsptouchResult executeForResult() throws RuntimeException;
30 |
31 | /**
32 | * Note: !!!Don't call the task at UI Main Thread or RuntimeException will
33 | * be thrown Execute the Esptouch Task and return the result
34 | *
35 | * Smart Config v2.4 support the API
36 | *
37 | * It will be blocked until the client receive result count >= expectTaskResultCount.
38 | * If it fail, it will return one fail result will be returned in the list.
39 | * If it is cancelled while executing,
40 | * if it has received some results, all of them will be returned in the list.
41 | * if it hasn't received any results, one cancel result will be returned in the list.
42 | *
43 | * @param expectTaskResultCount the expect result count(if expectTaskResultCount <= 0,
44 | * expectTaskResultCount = Integer.MAX_VALUE)
45 | * @return the list of IEsptouchResult
46 | * @throws RuntimeException
47 | */
48 | List executeForResults(int expectTaskResultCount) throws RuntimeException;
49 |
50 | /**
51 | * check whether the task is cancelled by user
52 | *
53 | * @return whether the task is cancelled by user
54 | */
55 | boolean isCancelled();
56 |
57 | /**
58 | * Set broadcast or multicast when post config info
59 | *
60 | * @param broadcast true is broadcast, false is multicast
61 | */
62 | void setPackageBroadcast(boolean broadcast);
63 | }
64 |
--------------------------------------------------------------------------------
/.circleci/config.yml:
--------------------------------------------------------------------------------
1 | version: 2.1
2 |
3 | executors:
4 | default:
5 | docker:
6 | - image: circleci/node:10
7 | working_directory: ~/project
8 |
9 | commands:
10 | attach_project:
11 | steps:
12 | - attach_workspace:
13 | at: ~/project
14 |
15 | jobs:
16 | install-dependencies:
17 | executor: default
18 | steps:
19 | - checkout
20 | - attach_project
21 | - restore_cache:
22 | keys:
23 | - dependencies-{{ checksum "package.json" }}
24 | - dependencies-
25 | - restore_cache:
26 | keys:
27 | - dependencies-example-{{ checksum "example/package.json" }}
28 | - dependencies-example-
29 | - run:
30 | name: Install dependencies
31 | command: |
32 | yarn install --cwd example --frozen-lockfile
33 | yarn install --frozen-lockfile
34 | - save_cache:
35 | key: dependencies-{{ checksum "package.json" }}
36 | paths: node_modules
37 | - save_cache:
38 | key: dependencies-example-{{ checksum "example/package.json" }}
39 | paths: example/node_modules
40 | - persist_to_workspace:
41 | root: .
42 | paths: .
43 |
44 | lint:
45 | executor: default
46 | steps:
47 | - attach_project
48 | - run:
49 | name: Lint files
50 | command: |
51 | yarn lint
52 |
53 | typescript:
54 | executor: default
55 | steps:
56 | - attach_project
57 | - run:
58 | name: Typecheck files
59 | command: |
60 | yarn typescript
61 |
62 | unit-tests:
63 | executor: default
64 | steps:
65 | - attach_project
66 | - run:
67 | name: Run unit tests
68 | command: |
69 | yarn test --coverage
70 | - store_artifacts:
71 | path: coverage
72 | destination: coverage
73 |
74 | build-package:
75 | executor: default
76 | steps:
77 | - attach_project
78 | - run:
79 | name: Build package
80 | command: |
81 | yarn prepare
82 |
83 | workflows:
84 | build-and-test:
85 | jobs:
86 | - install-dependencies
87 | - lint:
88 | requires:
89 | - install-dependencies
90 | - typescript:
91 | requires:
92 | - install-dependencies
93 | - unit-tests:
94 | requires:
95 | - install-dependencies
96 | - build-package:
97 | requires:
98 | - install-dependencies
99 |
--------------------------------------------------------------------------------
/ios/EspTouch/ESPUtils/ESPAES.m:
--------------------------------------------------------------------------------
1 | //
2 | // ESPAES.m
3 | // EspTouchDemo
4 | //
5 | // Created by AE on 2018/4/5.
6 | //
7 |
8 | #import "ESPAES.h"
9 | #import
10 |
11 | @implementation ESPAES
12 |
13 | - (instancetype)initWithKey:(NSString *)secretKey
14 | {
15 | self = [super init];
16 | if (self) {
17 | key = secretKey;
18 | }
19 | return self;
20 | }
21 |
22 | - (NSData *)AES128EncryptData:(NSData *)data {
23 | char keyPtr[kCCKeySizeAES128+1];
24 | bzero(keyPtr, sizeof(keyPtr));
25 | [key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];
26 | NSUInteger dataLength = [data length];
27 | size_t bufferSize = dataLength + kCCBlockSizeAES128;
28 | void *buffer = malloc(bufferSize);
29 | size_t numBytesEncrypted = 0;
30 | CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES128,
31 | kCCOptionPKCS7Padding | kCCOptionECBMode,
32 | keyPtr, kCCBlockSizeAES128,
33 | NULL,
34 | [data bytes], dataLength,
35 | buffer, bufferSize,
36 | &numBytesEncrypted);
37 | if (cryptStatus == kCCSuccess) {
38 | return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
39 | }
40 | free(buffer);
41 | return nil;
42 | }
43 |
44 | - (NSData *)AES128DecryptData:(NSData *)data {
45 | char keyPtr[kCCKeySizeAES128+1];
46 | bzero(keyPtr, sizeof(keyPtr));
47 | [key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];
48 | NSUInteger dataLength = [data length];
49 | size_t bufferSize = dataLength + kCCBlockSizeAES128;
50 | void *buffer = malloc(bufferSize);
51 | size_t numBytesDecrypted = 0;
52 | CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt, kCCAlgorithmAES128,
53 | kCCOptionPKCS7Padding | kCCOptionECBMode,
54 | keyPtr, kCCBlockSizeAES128,
55 | NULL,
56 | [data bytes], dataLength,
57 | buffer, bufferSize,
58 | &numBytesDecrypted);
59 | if (cryptStatus == kCCSuccess) {
60 | return [NSData dataWithBytesNoCopy:buffer length:numBytesDecrypted];
61 | }
62 | free(buffer);
63 | return nil;
64 | }
65 |
66 | @end
67 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # react-native-smartconfig-quan
2 |
3 | This library works both Android, IOS, Simulator
4 |
5 | ## Installation
6 |
7 | - step 1:
8 |
9 | ```sh
10 | yarn add react-native-smartconfig-quan
11 | ```
12 |
13 | - step 2:
14 |
15 | ```sh
16 | cd ios && pod install
17 | ```
18 |
19 | - step 3:
20 | Add permission in AndroidManifest.xml
21 |
22 | ```xml
23 |
24 |
25 |
26 | ```
27 |
28 | ## Usage
29 |
30 | ```js
31 | import SmartConfig from 'react-native-smartconfig-quan';
32 | import { Button, Text, View } from 'react-native';
33 | import React, { useState } from 'react';
34 |
35 | export default function App() {
36 |
37 | const [log, setLog] = useState('log here');
38 | let foundDevice = false;
39 |
40 | const wifiName = 'Viettel';
41 | const wifiPass = '0965677826';
42 | // you can random bssid of wifi, but it need correct format
43 | const wifiBssid = '8a:29:9c:69:af:9b';
44 |
45 | // timeout not work with android, on android default is 45s
46 | const TIME_OUT_SMART_CONFIG = 30 * 1000; // 30s
47 |
48 | function config() {
49 | setLog('configuring...');
50 | foundDevice = false;
51 |
52 | SmartConfig.start(wifiName, wifiBssid, wifiPass, TIME_OUT_SMART_CONFIG, (event) => {
53 | console.log(event);
54 | let { eventName, data } = event;
55 | if (eventName === 'onFoundDevice') {
56 | foundDevice = true;
57 | data = JSON.parse(data);
58 |
59 | // data in event is ip of ESP
60 | setLog('Found device\nip: ' + data.ip + '\nbssid: ' + data.bssid);
61 | } else {
62 | if (!foundDevice) {
63 | setLog('Not found');
64 | }
65 | }
66 | });
67 | }
68 |
69 | function stopConfig() {
70 | SmartConfig.stop();
71 | setLog('Stopped config');
72 | }
73 |
74 | return (
75 |
76 | {log}
77 |
78 |
79 | config()}/>
80 |
81 |
82 |
83 | stopConfig()}/>
84 |
85 |
86 |
87 | );
88 | }
89 | ```
90 |
--------------------------------------------------------------------------------
/example/ios/SmartconfigSwjavaExample/AppDelegate.m:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) Facebook, Inc. and its affiliates.
3 | *
4 | * This source code is licensed under the MIT license found in the
5 | * LICENSE file in the root directory of this source tree.
6 | */
7 |
8 | #import "AppDelegate.h"
9 |
10 | #import
11 | #import
12 | #import
13 |
14 | #if DEBUG
15 | #import
16 | #import
17 | #import
18 | #import
19 | #import
20 | #import
21 | static void InitializeFlipper(UIApplication *application) {
22 | FlipperClient *client = [FlipperClient sharedClient];
23 | SKDescriptorMapper *layoutDescriptorMapper = [[SKDescriptorMapper alloc] initWithDefaults];
24 | [client addPlugin:[[FlipperKitLayoutPlugin alloc] initWithRootNode:application withDescriptorMapper:layoutDescriptorMapper]];
25 | [client addPlugin:[[FKUserDefaultsPlugin alloc] initWithSuiteName:nil]];
26 | [client addPlugin:[FlipperKitReactPlugin new]];
27 | [client addPlugin:[[FlipperKitNetworkPlugin alloc] initWithNetworkAdapter:[SKIOSNetworkAdapter new]]];
28 | [client start];
29 | }
30 | #endif
31 |
32 | @implementation AppDelegate
33 |
34 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
35 | {
36 | #if DEBUG
37 | InitializeFlipper(application);
38 | #endif
39 | RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];
40 | RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge
41 | moduleName:@"SmartconfigSwjavaExample"
42 | initialProperties:nil];
43 |
44 | rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f green:1.0f blue:1.0f alpha:1];
45 |
46 | self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
47 | UIViewController *rootViewController = [UIViewController new];
48 | rootViewController.view = rootView;
49 | self.window.rootViewController = rootViewController;
50 | [self.window makeKeyAndVisible];
51 | return YES;
52 | }
53 |
54 | - (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
55 | {
56 | #if DEBUG
57 | return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil];
58 | #else
59 | return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
60 | #endif
61 | }
62 |
63 | @end
64 |
--------------------------------------------------------------------------------
/android/src/main/java/esptouch/protocol/DataCode.java:
--------------------------------------------------------------------------------
1 | package esptouch.protocol;
2 |
3 | import esptouch.task.ICodeData;
4 | import esptouch.util.ByteUtil;
5 | import esptouch.util.CRC8;
6 |
7 | /**
8 | * one data format:(data code should have 2 to 65 data)
9 | *
10 | * control byte high 4 bits low 4 bits
11 | * 1st 9bits: 0x0 crc(high) data(high)
12 | * 2nd 9bits: 0x1 sequence header
13 | * 3rd 9bits: 0x0 crc(low) data(low)
14 | *
15 | * sequence header: 0,1,2,...
16 | *
17 | * @author afunx
18 | */
19 | public class DataCode implements ICodeData {
20 |
21 | public static final int DATA_CODE_LEN = 6;
22 |
23 | private static final int INDEX_MAX = 127;
24 |
25 | private final byte mSeqHeader;
26 | private final byte mDataHigh;
27 | private final byte mDataLow;
28 | // the crc here means the crc of the data and sequence header be transformed
29 | // it is calculated by index and data to be transformed
30 | private final byte mCrcHigh;
31 | private final byte mCrcLow;
32 |
33 | /**
34 | * Constructor of DataCode
35 | *
36 | * @param u8 the character to be transformed
37 | * @param index the index of the char
38 | */
39 | public DataCode(char u8, int index) {
40 | if (index > INDEX_MAX) {
41 | throw new RuntimeException("index > INDEX_MAX");
42 | }
43 | byte[] dataBytes = ByteUtil.splitUint8To2bytes(u8);
44 | mDataHigh = dataBytes[0];
45 | mDataLow = dataBytes[1];
46 | CRC8 crc8 = new CRC8();
47 | crc8.update(ByteUtil.convertUint8toByte(u8));
48 | crc8.update(index);
49 | byte[] crcBytes = ByteUtil.splitUint8To2bytes((char) crc8.getValue());
50 | mCrcHigh = crcBytes[0];
51 | mCrcLow = crcBytes[1];
52 | mSeqHeader = (byte) index;
53 | }
54 |
55 | @Override
56 | public byte[] getBytes() {
57 | byte[] dataBytes = new byte[DATA_CODE_LEN];
58 | dataBytes[0] = 0x00;
59 | dataBytes[1] = ByteUtil.combine2bytesToOne(mCrcHigh, mDataHigh);
60 | dataBytes[2] = 0x01;
61 | dataBytes[3] = mSeqHeader;
62 | dataBytes[4] = 0x00;
63 | dataBytes[5] = ByteUtil.combine2bytesToOne(mCrcLow, mDataLow);
64 | return dataBytes;
65 | }
66 |
67 | @Override
68 | public String toString() {
69 | StringBuilder sb = new StringBuilder();
70 | byte[] dataBytes = getBytes();
71 | for (int i = 0; i < DATA_CODE_LEN; i++) {
72 | String hexString = ByteUtil.convertByte2HexString(dataBytes[i]);
73 | sb.append("0x");
74 | if (hexString.length() == 1) {
75 | sb.append("0");
76 | }
77 | sb.append(hexString).append(" ");
78 | }
79 | return sb.toString();
80 | }
81 |
82 | @Override
83 | public char[] getU8s() {
84 | throw new RuntimeException("DataCode don't support getU8s()");
85 | }
86 |
87 | }
88 |
--------------------------------------------------------------------------------
/example/android/app/src/main/java/com/example/reactnativesmartconfigswjava/MainApplication.java:
--------------------------------------------------------------------------------
1 | package com.example.reactnativesmartconfigswjava;
2 |
3 | import android.app.Application;
4 | import android.content.Context;
5 | import com.facebook.react.PackageList;
6 | import com.facebook.react.ReactApplication;
7 | import com.facebook.react.ReactNativeHost;
8 | import com.facebook.react.ReactPackage;
9 | import com.facebook.react.ReactInstanceManager;
10 | import com.facebook.soloader.SoLoader;
11 | import java.lang.reflect.InvocationTargetException;
12 | import java.util.List;
13 |
14 | import com.reactnativesmartconfigswjava.SmartconfigSwjavaPackage;
15 |
16 | public class MainApplication extends Application implements ReactApplication {
17 |
18 | private final ReactNativeHost mReactNativeHost =
19 | new ReactNativeHost(this) {
20 | @Override
21 | public boolean getUseDeveloperSupport() {
22 | return BuildConfig.DEBUG;
23 | }
24 |
25 | @Override
26 | protected List getPackages() {
27 | @SuppressWarnings("UnnecessaryLocalVariable")
28 | List packages = new PackageList(this).getPackages();
29 | // Packages that cannot be autolinked yet can be added manually here, for SmartconfigSwjavaExample:
30 | // packages.add(new MyReactNativePackage());
31 | packages.add(new SmartconfigSwjavaPackage());
32 |
33 | return packages;
34 | }
35 |
36 | @Override
37 | protected String getJSMainModuleName() {
38 | return "index";
39 | }
40 | };
41 |
42 | @Override
43 | public ReactNativeHost getReactNativeHost() {
44 | return mReactNativeHost;
45 | }
46 |
47 | @Override
48 | public void onCreate() {
49 | super.onCreate();
50 | SoLoader.init(this, /* native exopackage */ false);
51 | initializeFlipper(this, getReactNativeHost().getReactInstanceManager()); // Remove this line if you don't want Flipper enabled
52 | }
53 |
54 | /**
55 | * Loads Flipper in React Native templates.
56 | *
57 | * @param context
58 | */
59 | private static void initializeFlipper(Context context, ReactInstanceManager reactInstanceManager) {
60 | if (BuildConfig.DEBUG) {
61 | try {
62 | /*
63 | We use reflection here to pick up the class that initializes Flipper,
64 | since Flipper library is not available in release mode
65 | */
66 | Class> aClass = Class.forName("com.reactnativesmartconfigswjavaExample.ReactNativeFlipper");
67 | aClass
68 | .getMethod("initializeFlipper", Context.class, ReactInstanceManager.class)
69 | .invoke(null, context, reactInstanceManager);
70 | } catch (ClassNotFoundException e) {
71 | e.printStackTrace();
72 | } catch (NoSuchMethodException e) {
73 | e.printStackTrace();
74 | } catch (IllegalAccessException e) {
75 | e.printStackTrace();
76 | } catch (InvocationTargetException e) {
77 | e.printStackTrace();
78 | }
79 | }
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/android/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 |
17 | @if "%DEBUG%" == "" @echo off
18 | @rem ##########################################################################
19 | @rem
20 | @rem Gradle startup script for Windows
21 | @rem
22 | @rem ##########################################################################
23 |
24 | @rem Set local scope for the variables with windows NT shell
25 | if "%OS%"=="Windows_NT" setlocal
26 |
27 | set DIRNAME=%~dp0
28 | if "%DIRNAME%" == "" set DIRNAME=.
29 | set APP_BASE_NAME=%~n0
30 | set APP_HOME=%DIRNAME%
31 |
32 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
33 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
34 |
35 | @rem Find java.exe
36 | if defined JAVA_HOME goto findJavaFromJavaHome
37 |
38 | set JAVA_EXE=java.exe
39 | %JAVA_EXE% -version >NUL 2>&1
40 | if "%ERRORLEVEL%" == "0" goto init
41 |
42 | echo.
43 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
44 | echo.
45 | echo Please set the JAVA_HOME variable in your environment to match the
46 | echo location of your Java installation.
47 |
48 | goto fail
49 |
50 | :findJavaFromJavaHome
51 | set JAVA_HOME=%JAVA_HOME:"=%
52 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
53 |
54 | if exist "%JAVA_EXE%" goto init
55 |
56 | echo.
57 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
58 | echo.
59 | echo Please set the JAVA_HOME variable in your environment to match the
60 | echo location of your Java installation.
61 |
62 | goto fail
63 |
64 | :init
65 | @rem Get command-line arguments, handling Windows variants
66 |
67 | if not "%OS%" == "Windows_NT" goto win9xME_args
68 |
69 | :win9xME_args
70 | @rem Slurp the command line arguments.
71 | set CMD_LINE_ARGS=
72 | set _SKIP=2
73 |
74 | :win9xME_args_slurp
75 | if "x%~1" == "x" goto execute
76 |
77 | set CMD_LINE_ARGS=%*
78 |
79 | :execute
80 | @rem Setup the command line
81 |
82 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
83 |
84 | @rem Execute Gradle
85 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
86 |
87 | :end
88 | @rem End local scope for the variables with windows NT shell
89 | if "%ERRORLEVEL%"=="0" goto mainEnd
90 |
91 | :fail
92 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
93 | rem the _cmd.exe /c_ return code!
94 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
95 | exit /b 1
96 |
97 | :mainEnd
98 | if "%OS%"=="Windows_NT" endlocal
99 |
100 | :omega
101 |
--------------------------------------------------------------------------------
/example/android/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem http://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 |
17 | @if "%DEBUG%" == "" @echo off
18 | @rem ##########################################################################
19 | @rem
20 | @rem Gradle startup script for Windows
21 | @rem
22 | @rem ##########################################################################
23 |
24 | @rem Set local scope for the variables with windows NT shell
25 | if "%OS%"=="Windows_NT" setlocal
26 |
27 | set DIRNAME=%~dp0
28 | if "%DIRNAME%" == "" set DIRNAME=.
29 | set APP_BASE_NAME=%~n0
30 | set APP_HOME=%DIRNAME%
31 |
32 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
33 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
34 |
35 | @rem Find java.exe
36 | if defined JAVA_HOME goto findJavaFromJavaHome
37 |
38 | set JAVA_EXE=java.exe
39 | %JAVA_EXE% -version >NUL 2>&1
40 | if "%ERRORLEVEL%" == "0" goto init
41 |
42 | echo.
43 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
44 | echo.
45 | echo Please set the JAVA_HOME variable in your environment to match the
46 | echo location of your Java installation.
47 |
48 | goto fail
49 |
50 | :findJavaFromJavaHome
51 | set JAVA_HOME=%JAVA_HOME:"=%
52 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
53 |
54 | if exist "%JAVA_EXE%" goto init
55 |
56 | echo.
57 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
58 | echo.
59 | echo Please set the JAVA_HOME variable in your environment to match the
60 | echo location of your Java installation.
61 |
62 | goto fail
63 |
64 | :init
65 | @rem Get command-line arguments, handling Windows variants
66 |
67 | if not "%OS%" == "Windows_NT" goto win9xME_args
68 |
69 | :win9xME_args
70 | @rem Slurp the command line arguments.
71 | set CMD_LINE_ARGS=
72 | set _SKIP=2
73 |
74 | :win9xME_args_slurp
75 | if "x%~1" == "x" goto execute
76 |
77 | set CMD_LINE_ARGS=%*
78 |
79 | :execute
80 | @rem Setup the command line
81 |
82 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
83 |
84 | @rem Execute Gradle
85 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
86 |
87 | :end
88 | @rem End local scope for the variables with windows NT shell
89 | if "%ERRORLEVEL%"=="0" goto mainEnd
90 |
91 | :fail
92 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
93 | rem the _cmd.exe /c_ return code!
94 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
95 | exit /b 1
96 |
97 | :mainEnd
98 | if "%OS%"=="Windows_NT" endlocal
99 |
100 | :omega
101 |
--------------------------------------------------------------------------------
/example/android/app/src/debug/java/com/example/reactnativesmartconfigswjava/ReactNativeFlipper.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) Facebook, Inc. and its affiliates.
3 | *
4 | * This source code is licensed under the MIT license found in the LICENSE file in the root
5 | * directory of this source tree.
6 | */
7 | package com.example.reactnativesmartconfigswjava;
8 |
9 | import android.content.Context;
10 | import com.facebook.flipper.android.AndroidFlipperClient;
11 | import com.facebook.flipper.android.utils.FlipperUtils;
12 | import com.facebook.flipper.core.FlipperClient;
13 | import com.facebook.flipper.plugins.crashreporter.CrashReporterPlugin;
14 | import com.facebook.flipper.plugins.databases.DatabasesFlipperPlugin;
15 | import com.facebook.flipper.plugins.fresco.FrescoFlipperPlugin;
16 | import com.facebook.flipper.plugins.inspector.DescriptorMapping;
17 | import com.facebook.flipper.plugins.inspector.InspectorFlipperPlugin;
18 | import com.facebook.flipper.plugins.network.FlipperOkhttpInterceptor;
19 | import com.facebook.flipper.plugins.network.NetworkFlipperPlugin;
20 | import com.facebook.flipper.plugins.react.ReactFlipperPlugin;
21 | import com.facebook.flipper.plugins.sharedpreferences.SharedPreferencesFlipperPlugin;
22 | import com.facebook.react.ReactInstanceManager;
23 | import com.facebook.react.bridge.ReactContext;
24 | import com.facebook.react.modules.network.NetworkingModule;
25 | import okhttp3.OkHttpClient;
26 |
27 | public class ReactNativeFlipper {
28 | public static void initializeFlipper(Context context, ReactInstanceManager reactInstanceManager) {
29 | if (FlipperUtils.shouldEnableFlipper(context)) {
30 | final FlipperClient client = AndroidFlipperClient.getInstance(context);
31 | client.addPlugin(new InspectorFlipperPlugin(context, DescriptorMapping.withDefaults()));
32 | client.addPlugin(new ReactFlipperPlugin());
33 | client.addPlugin(new DatabasesFlipperPlugin(context));
34 | client.addPlugin(new SharedPreferencesFlipperPlugin(context));
35 | client.addPlugin(CrashReporterPlugin.getInstance());
36 | NetworkFlipperPlugin networkFlipperPlugin = new NetworkFlipperPlugin();
37 | NetworkingModule.setCustomClientBuilder(
38 | new NetworkingModule.CustomClientBuilder() {
39 | @Override
40 | public void apply(OkHttpClient.Builder builder) {
41 | builder.addNetworkInterceptor(new FlipperOkhttpInterceptor(networkFlipperPlugin));
42 | }
43 | });
44 | client.addPlugin(networkFlipperPlugin);
45 | client.start();
46 | // Fresco Plugin needs to ensure that ImagePipelineFactory is initialized
47 | // Hence we run if after all native modules have been initialized
48 | ReactContext reactContext = reactInstanceManager.getCurrentReactContext();
49 | if (reactContext == null) {
50 | reactInstanceManager.addReactInstanceEventListener(
51 | new ReactInstanceManager.ReactInstanceEventListener() {
52 | @Override
53 | public void onReactContextInitialized(ReactContext reactContext) {
54 | reactInstanceManager.removeReactInstanceEventListener(this);
55 | reactContext.runOnNativeModulesQueueThread(
56 | new Runnable() {
57 | @Override
58 | public void run() {
59 | client.addPlugin(new FrescoFlipperPlugin());
60 | }
61 | });
62 | }
63 | });
64 | } else {
65 | client.addPlugin(new FrescoFlipperPlugin());
66 | }
67 | }
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/ios/EspTouch/ESPUtils/ESP_ByteUtil.h:
--------------------------------------------------------------------------------
1 | //
2 | // ESP_ByteUtil.h
3 | // EspTouchDemo
4 | //
5 | // Created by fby on 4/7/15.
6 | // Copyright (c) 2015 fby. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface ESP_ByteUtil : NSObject
12 |
13 | #define ESPTOUCH_NSStringEncoding NSUTF8StringEncoding
14 |
15 | /**
16 | * Convert uint8 into char( we treat char as uint8)
17 | *
18 | * @param uint8
19 | * the unit8 to be converted
20 | * @return the byte of the unint8
21 | */
22 | + (Byte) convertUint8toByte:(char) uint8;
23 |
24 | /**
25 | * Convert char into uint8( we treat char as uint8 )
26 | *
27 | * @param b
28 | * the byte to be converted
29 | * @return the UInt8(uint8)
30 | */
31 | + (UInt8) convertByte2Uint8:(Byte) b;
32 |
33 | /**
34 | * Convert byte to Hex String
35 | *
36 | * @param b
37 | * the byte to be converted
38 | * @return the Hex String
39 | */
40 | + (NSString *) convertByte2HexString:(Byte) b;
41 |
42 | /**
43 | * Split uint8 to 2 bytes of high byte and low byte. e.g. 20 = 0x14 should
44 | * be split to [0x01,0x04] 0x01 is high byte and 0x04 is low byte
45 | *
46 | * @param uint8
47 | * the char(uint8)
48 | * @return the high and low bytes be split, byte[0] is high and byte[1] is
49 | * low
50 | */
51 | + (NSData *) splitUint8To2Bytes: (UInt8) uint8;
52 |
53 | /**
54 | * Combine 2 bytes (high byte and low byte) to one whole byte
55 | *
56 | * @param high
57 | * the high byte
58 | * @param low
59 | * the low byte
60 | * @return the whole byte
61 | */
62 | + (Byte) combine2bytesToOneWithHigh: (Byte) high andLow: (Byte) low;
63 |
64 | /**
65 | * Combine 2 bytes (high byte and low byte) to one UInt16
66 | *
67 | * @param high
68 | * the high byte
69 | * @param low
70 | * the low byte
71 | * @return the UInt8
72 | */
73 | + (UInt16) combine2bytesToU16WithHigh: (Byte) high andLow: (Byte) low;
74 |
75 | /**
76 | * Generate the random byte to be sent
77 | *
78 | * @return the random byte
79 | */
80 | + (Byte) randomByte;
81 |
82 | /**
83 | * Generate the random byte to be sent
84 | *
85 | * @param len
86 | * the len presented by u8
87 | * @return the byte[] to be sent
88 | */
89 | + (NSData *) randomBytes: (UInt8) len;
90 |
91 | + (NSData *) genSpecBytesWithU16: (UInt16) len;
92 |
93 | /**
94 | * Generate the specific byte to be sent
95 | * @param len
96 | * the len presented by byte
97 | * @return the byte[]
98 | */
99 | + (NSData *) genSpecBytesWithU8:(Byte) len;
100 |
101 | + (NSString *) parseBssid:(Byte[]) bssidBytes Offset: (int) offset Count: (int) count;
102 |
103 | /**
104 | * parse "24,-2,52,-102,-93,-60" to "18,fe,34,9a,a3,c4" parse the bssid from
105 | * hex to String
106 | *
107 | * @param bssidBytes
108 | * the hex bytes bssid, e.g. {24,-2,52,-102,-93,-60}
109 | * @param len
110 | * the len of bssidBytes
111 | * @return the String of bssid, e.g. 18fe349aa3c4
112 | */
113 | + (NSString *) parseBssid:(Byte[]) bssidBytes Len: (int) len;
114 |
115 | /**
116 | * @param string the string to be used
117 | * @return the Byte[] of string according to ESPTOUCH_NSStringEncoding
118 | */
119 | + (NSData *) getBytesByNSString: (NSString *)string;
120 |
121 | /**
122 | * get hex string transformed by data
123 | * @param data the data to be transformed
124 | * @return the hex String transformed by data
125 | */
126 | + (NSString *) getHexStringByData: (NSData *)data;
127 |
128 | @end
129 |
--------------------------------------------------------------------------------
/android/src/main/java/esptouch/util/EspAES.java:
--------------------------------------------------------------------------------
1 | package esptouch.util;
2 |
3 | import java.security.InvalidAlgorithmParameterException;
4 | import java.security.InvalidKeyException;
5 | import java.security.NoSuchAlgorithmException;
6 |
7 | import javax.crypto.BadPaddingException;
8 | import javax.crypto.Cipher;
9 | import javax.crypto.IllegalBlockSizeException;
10 | import javax.crypto.NoSuchPaddingException;
11 | import javax.crypto.spec.IvParameterSpec;
12 | import javax.crypto.spec.SecretKeySpec;
13 |
14 | public class EspAES {
15 | private static final String TRANSFORMATION_DEFAULT = "AES/ECB/PKCS5Padding";
16 |
17 | private final byte[] mKey;
18 | private final byte[] mIV;
19 | private final String mTransformation;
20 | private Cipher mEncryptCipher;
21 | private Cipher mDecryptCipher;
22 |
23 | public EspAES(byte[] key) {
24 | this(key, null, TRANSFORMATION_DEFAULT);
25 | }
26 |
27 | public EspAES(byte[] key, String transformation) {
28 | this(key, null, transformation);
29 | }
30 |
31 | public EspAES(byte[] key, byte[] iv) {
32 | this(key, iv, TRANSFORMATION_DEFAULT);
33 | }
34 |
35 | public EspAES(byte[] key, byte[] iv, String transformation) {
36 | mKey = key;
37 | mIV = iv;
38 | mTransformation = transformation;
39 |
40 | mEncryptCipher = createEncryptCipher();
41 | mDecryptCipher = createDecryptCipher();
42 | }
43 |
44 | private Cipher createEncryptCipher() {
45 | try {
46 | Cipher cipher = Cipher.getInstance(mTransformation);
47 |
48 | SecretKeySpec secretKeySpec = new SecretKeySpec(mKey, "AES");
49 | if (mIV == null) {
50 | cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
51 | } else {
52 | IvParameterSpec parameterSpec = new IvParameterSpec(mIV);
53 | cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, parameterSpec);
54 | }
55 |
56 | return cipher;
57 | } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | InvalidAlgorithmParameterException
58 | e) {
59 | e.printStackTrace();
60 | }
61 |
62 | return null;
63 | }
64 |
65 | private Cipher createDecryptCipher() {
66 | try {
67 | Cipher cipher = Cipher.getInstance(mTransformation);
68 |
69 | SecretKeySpec secretKeySpec = new SecretKeySpec(mKey, "AES");
70 | if (mIV == null) {
71 | cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);
72 | } else {
73 | IvParameterSpec parameterSpec = new IvParameterSpec(mIV);
74 | cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, parameterSpec);
75 | }
76 |
77 | return cipher;
78 | } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | InvalidAlgorithmParameterException
79 | e) {
80 | e.printStackTrace();
81 | }
82 |
83 | return null;
84 | }
85 |
86 | public byte[] encrypt(byte[] content) {
87 | try {
88 | return mEncryptCipher.doFinal(content);
89 | } catch (BadPaddingException | IllegalBlockSizeException e) {
90 | e.printStackTrace();
91 | }
92 | return null;
93 | }
94 |
95 | public byte[] decrypt(byte[] content) {
96 | try {
97 | return mDecryptCipher.doFinal(content);
98 | } catch (BadPaddingException | IllegalBlockSizeException e) {
99 | e.printStackTrace();
100 | }
101 |
102 | return null;
103 | }
104 | }
105 |
--------------------------------------------------------------------------------
/ios/EspTouch/ESPUtils/ESP_WifiUtil.m:
--------------------------------------------------------------------------------
1 | //
2 | // ESP_WifiUtil.m
3 | // EspTouchDemo
4 | //
5 | // Created by fby on 6/15/16.
6 | // Copyright © 2016 fby. All rights reserved.
7 | //
8 |
9 | #import "ESP_WifiUtil.h"
10 |
11 | #include
12 | #include
13 | #include
14 |
15 | #define IOS_CELLULAR @"pdp_ip0"
16 | #define IOS_WIFI @"en0"
17 | #define IOS_VPN @"utun0"
18 | #define IP_ADDR_IPv4 @"ipv4"
19 | #define IP_ADDR_IPv6 @"ipv6"
20 |
21 | @implementation ESP_WifiUtil
22 |
23 | + (NSString *)getIPAddress:(BOOL)preferIPv4
24 | {
25 | NSArray *searchArray = preferIPv4 ?
26 | @[ IOS_VPN @"/" IP_ADDR_IPv4, IOS_VPN @"/" IP_ADDR_IPv6, IOS_WIFI @"/" IP_ADDR_IPv4, IOS_WIFI @"/" IP_ADDR_IPv6, IOS_CELLULAR @"/" IP_ADDR_IPv4, IOS_CELLULAR @"/" IP_ADDR_IPv6 ] :
27 | @[ IOS_VPN @"/" IP_ADDR_IPv6, IOS_VPN @"/" IP_ADDR_IPv4, IOS_WIFI @"/" IP_ADDR_IPv6, IOS_WIFI @"/" IP_ADDR_IPv4, IOS_CELLULAR @"/" IP_ADDR_IPv6, IOS_CELLULAR @"/" IP_ADDR_IPv4 ] ;
28 |
29 | NSDictionary *addresses = [self getIPAddresses];
30 | // NSLog(@"addresses: %@", addresses);
31 |
32 | __block NSString *address;
33 | [searchArray enumerateObjectsUsingBlock:^(NSString *key, NSUInteger idx, BOOL *stop)
34 | {
35 | address = addresses[key];
36 | if(address) *stop = YES;
37 | } ];
38 | return address ? address : @"0.0.0.0";
39 | }
40 |
41 | + (NSDictionary *)getIPAddresses
42 | {
43 | NSMutableDictionary *addresses = [NSMutableDictionary dictionaryWithCapacity:8];
44 |
45 | // retrieve the current interfaces - returns 0 on success
46 | struct ifaddrs *interfaces;
47 | if(!getifaddrs(&interfaces)) {
48 | // Loop through linked list of interfaces
49 | struct ifaddrs *interface;
50 | for(interface=interfaces; interface; interface=interface->ifa_next) {
51 | if(!(interface->ifa_flags & IFF_UP) /* || (interface->ifa_flags & IFF_LOOPBACK) */ ) {
52 | continue; // deeply nested code harder to read
53 | }
54 | const struct sockaddr_in *addr = (const struct sockaddr_in*)interface->ifa_addr;
55 | char addrBuf[ MAX(INET_ADDRSTRLEN, INET6_ADDRSTRLEN) ];
56 | if(addr && (addr->sin_family==AF_INET || addr->sin_family==AF_INET6)) {
57 | NSString *name = [NSString stringWithUTF8String:interface->ifa_name];
58 | NSString *type;
59 | if(addr->sin_family == AF_INET) {
60 | if(inet_ntop(AF_INET, &addr->sin_addr, addrBuf, INET_ADDRSTRLEN)) {
61 | type = IP_ADDR_IPv4;
62 | }
63 | } else {
64 | const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6*)interface->ifa_addr;
65 | if(inet_ntop(AF_INET6, &addr6->sin6_addr, addrBuf, INET6_ADDRSTRLEN)) {
66 | type = IP_ADDR_IPv6;
67 | }
68 | }
69 | if(type) {
70 | NSString *key = [NSString stringWithFormat:@"%@/%@", name, type];
71 | addresses[key] = [NSString stringWithUTF8String:addrBuf];
72 | }
73 | }
74 | }
75 | // Free memory
76 | freeifaddrs(interfaces);
77 | }
78 | return [addresses count] ? addresses : nil;
79 | }
80 |
81 | + (NSString *)getIPAddress4
82 | {
83 | NSString *key = [NSString stringWithFormat:@"%@/%@",IOS_WIFI,IP_ADDR_IPv4];
84 | NSString *ipv4 = [[self getIPAddresses]objectForKey:key];
85 | return ipv4;
86 | }
87 |
88 | + (NSString *)getIpAddress6
89 | {
90 | NSString *key = [NSString stringWithFormat:@"%@/%@",IOS_WIFI,IP_ADDR_IPv6];
91 | NSString *ipv6 = [[self getIPAddresses]objectForKey:key];
92 | return ipv6;
93 | }
94 |
95 | @end
96 |
--------------------------------------------------------------------------------
/example/ios/Podfile:
--------------------------------------------------------------------------------
1 | platform :ios, '9.0'
2 | require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules'
3 |
4 | def add_flipper_pods!
5 | version = '~> 0.33.1'
6 | pod 'FlipperKit', version, :configuration => 'Debug'
7 | pod 'FlipperKit/FlipperKitLayoutPlugin', version, :configuration => 'Debug'
8 | pod 'FlipperKit/SKIOSNetworkPlugin', version, :configuration => 'Debug'
9 | pod 'FlipperKit/FlipperKitUserDefaultsPlugin', version, :configuration => 'Debug'
10 | pod 'FlipperKit/FlipperKitReactPlugin', version, :configuration => 'Debug'
11 | end
12 | # Post Install processing for Flipper
13 | def flipper_post_install(installer)
14 | installer.pods_project.targets.each do |target|
15 | if target.name == 'YogaKit'
16 | target.build_configurations.each do |config|
17 | config.build_settings['SWIFT_VERSION'] = '4.1'
18 | end
19 | end
20 | end
21 | end
22 |
23 | target 'SmartconfigSwjavaExample' do
24 | # Pods for SmartconfigSwjavaExample
25 | pod 'FBLazyVector', :path => "../node_modules/react-native/Libraries/FBLazyVector"
26 | pod 'FBReactNativeSpec', :path => "../node_modules/react-native/Libraries/FBReactNativeSpec"
27 | pod 'RCTRequired', :path => "../node_modules/react-native/Libraries/RCTRequired"
28 | pod 'RCTTypeSafety', :path => "../node_modules/react-native/Libraries/TypeSafety"
29 | pod 'React', :path => '../node_modules/react-native/'
30 | pod 'React-Core', :path => '../node_modules/react-native/'
31 | pod 'React-CoreModules', :path => '../node_modules/react-native/React/CoreModules'
32 | pod 'React-Core/DevSupport', :path => '../node_modules/react-native/'
33 | pod 'React-RCTActionSheet', :path => '../node_modules/react-native/Libraries/ActionSheetIOS'
34 | pod 'React-RCTAnimation', :path => '../node_modules/react-native/Libraries/NativeAnimation'
35 | pod 'React-RCTBlob', :path => '../node_modules/react-native/Libraries/Blob'
36 | pod 'React-RCTImage', :path => '../node_modules/react-native/Libraries/Image'
37 | pod 'React-RCTLinking', :path => '../node_modules/react-native/Libraries/LinkingIOS'
38 | pod 'React-RCTNetwork', :path => '../node_modules/react-native/Libraries/Network'
39 | pod 'React-RCTSettings', :path => '../node_modules/react-native/Libraries/Settings'
40 | pod 'React-RCTText', :path => '../node_modules/react-native/Libraries/Text'
41 | pod 'React-RCTVibration', :path => '../node_modules/react-native/Libraries/Vibration'
42 | pod 'React-Core/RCTWebSocket', :path => '../node_modules/react-native/'
43 |
44 | pod 'React-cxxreact', :path => '../node_modules/react-native/ReactCommon/cxxreact'
45 | pod 'React-jsi', :path => '../node_modules/react-native/ReactCommon/jsi'
46 | pod 'React-jsiexecutor', :path => '../node_modules/react-native/ReactCommon/jsiexecutor'
47 | pod 'React-jsinspector', :path => '../node_modules/react-native/ReactCommon/jsinspector'
48 | pod 'ReactCommon/callinvoker', :path => "../node_modules/react-native/ReactCommon"
49 | pod 'ReactCommon/turbomodule/core', :path => "../node_modules/react-native/ReactCommon"
50 | pod 'Yoga', :path => '../node_modules/react-native/ReactCommon/yoga', :modular_headers => true
51 |
52 | pod 'DoubleConversion', :podspec => '../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec'
53 | pod 'glog', :podspec => '../node_modules/react-native/third-party-podspecs/glog.podspec'
54 | pod 'Folly', :podspec => '../node_modules/react-native/third-party-podspecs/Folly.podspec'
55 |
56 | pod 'react-native-smartconfig-swjava', :path => '../..'
57 |
58 | use_native_modules!
59 |
60 | # Enables Flipper.
61 | #
62 | # Note that if you have use_frameworks! enabled, Flipper will not work and
63 | # you should disable these next few lines.
64 | add_flipper_pods!
65 | post_install do |installer|
66 | flipper_post_install(installer)
67 | end
68 | end
69 |
--------------------------------------------------------------------------------
/example/ios/SmartconfigSwjavaExample/Base.lproj/LaunchScreen.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/ios/SmartconfigSwjava.swift:
--------------------------------------------------------------------------------
1 | import UIKit
2 |
3 | @objc(SmartconfigSwjava)
4 | class SmartconfigSwjava: RCTEventEmitter {
5 |
6 | let eventNameToRN = "SmartConfig"
7 |
8 | var SSID:String = ""
9 | var PASS:String = ""
10 | var BSSID:String = ""
11 |
12 | var isConfirmState: Bool!
13 | var condition:NSCondition!
14 | var esptouchTask: ESPTouchTask!
15 | //
16 | @objc var wifiPass = ""
17 | @objc var wifiName = ""
18 | var ipResult = "";
19 |
20 | init(fromString string: NSString) {
21 | super.init()
22 | condition = NSCondition()
23 | }
24 |
25 | convenience override init() {
26 | self.init(fromString:"John") // calls above mentioned controller with default name
27 | }
28 |
29 |
30 | /* Configuration result */
31 | func executeForResult(timeScan: Int) -> ESPTouchResult {
32 | print("executeForResult")
33 | // Sync lock
34 | condition.lock()
35 | // Get the parameters required for configuration
36 | esptouchTask = ESPTouchTask(apSsid: SSID, andApBssid: BSSID, andApPwd: PASS, andTimeoutMillisecond : Int32(timeScan))
37 | // Set up proxy
38 | condition.unlock()
39 | let esptouchResult: ESPTouchResult = self.esptouchTask.executeForResult()
40 | return esptouchResult
41 | }
42 |
43 | /* Cancel distribution network */
44 | func cancel() {
45 | print("cancel")
46 | condition.lock()
47 | if self.esptouchTask != nil {
48 | self.esptouchTask.interrupt()
49 | }
50 | condition.unlock()
51 | }
52 |
53 |
54 | override func supportedEvents() -> [String]! {
55 | return [ eventNameToRN ]
56 | }
57 |
58 | // Takes an errorCallback as a parameter so that you know when things go wrong.
59 | // This will make more sense once we get to the Javascript
60 | // ["status": "penđing smartconfig", "data" : nil]
61 | //
62 |
63 | @objc func stop(){
64 | self.cancel();
65 | }
66 |
67 | @objc(start:bssid:password:timeScan:errorCallback:) func start( ssid: String, bssid: String, password:String, timeScan: Int, errorCallback: @escaping RCTResponseSenderBlock) {
68 | print("wifiName", ssid, bssid, password)
69 |
70 | if !ssid.isEmpty {
71 | SSID = ssid
72 | PASS = password
73 | BSSID = bssid
74 |
75 | print("SSID" , SSID, "PASS", PASS)
76 | print("Configuration in progress...")
77 |
78 | let queue = DispatchQueue.global(qos: .default)
79 | queue.async {
80 | print("Thread is working...")
81 |
82 | let esptouchResult: ESPTouchResult = self.executeForResult(timeScan: timeScan)
83 | DispatchQueue.main.async(execute: {
84 | if !esptouchResult.isCancelled {
85 | print(" esptouchResult.description", esptouchResult.description)
86 | // IP拼接
87 |
88 | if (esptouchResult.getAddressString() != nil) {
89 | let ip = esptouchResult.getAddressString() ?? ""
90 | let bssid = esptouchResult.bssid ?? ""
91 | let data = "{\"ip\":\"" + ip + "\", \"bssid\":\"" + bssid + "\"}"
92 | self.sendEventToRN(eventName: "onFoundDevice", data: data)
93 | }else {
94 | self.sendEventToRN(eventName: "onFinishScan", data: "")
95 | }
96 | }
97 | })
98 | }
99 | } else {
100 | print("wifi disconnected")
101 | self.sendEventToRN(eventName: "onFinishScan", data: "")
102 | return
103 | }
104 | }
105 |
106 | func sendEventToRN(eventName: String, data: String) {
107 | self.sendEvent(withName: eventNameToRN, body: ["eventName":eventName, "data":data])
108 | }
109 | }
110 |
--------------------------------------------------------------------------------
/android/build.gradle:
--------------------------------------------------------------------------------
1 | buildscript {
2 | // Buildscript is evaluated before everything else so we can't use getExtOrDefault
3 | def kotlin_version = rootProject.ext.has('kotlinVersion') ? rootProject.ext.get('kotlinVersion') : project.properties['SmartconfigSwjava_kotlinVersion']
4 |
5 | repositories {
6 | google()
7 | jcenter()
8 | }
9 |
10 | dependencies {
11 | classpath 'com.android.tools.build:gradle:3.2.1'
12 | // noinspection DifferentKotlinGradleVersion
13 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
14 | }
15 | }
16 |
17 | apply plugin: 'com.android.library'
18 | apply plugin: 'kotlin-android'
19 |
20 | def getExtOrDefault(name) {
21 | return rootProject.ext.has(name) ? rootProject.ext.get(name) : project.properties['SmartconfigSwjava_' + name]
22 | }
23 |
24 | def getExtOrIntegerDefault(name) {
25 | return rootProject.ext.has(name) ? rootProject.ext.get(name) : (project.properties['SmartconfigSwjava_' + name]).toInteger()
26 | }
27 |
28 | android {
29 | compileSdkVersion getExtOrIntegerDefault('compileSdkVersion')
30 | buildToolsVersion getExtOrDefault('buildToolsVersion')
31 | defaultConfig {
32 | minSdkVersion 16
33 | targetSdkVersion getExtOrIntegerDefault('targetSdkVersion')
34 | versionCode 1
35 | versionName "1.0"
36 |
37 | }
38 |
39 | buildTypes {
40 | release {
41 | minifyEnabled false
42 | }
43 | }
44 | lintOptions {
45 | disable 'GradleCompatible'
46 | }
47 | compileOptions {
48 | sourceCompatibility JavaVersion.VERSION_1_8
49 | targetCompatibility JavaVersion.VERSION_1_8
50 | }
51 | }
52 |
53 | repositories {
54 | mavenCentral()
55 | jcenter()
56 | google()
57 |
58 | def found = false
59 | def defaultDir = null
60 | def androidSourcesName = 'React Native sources'
61 |
62 | if (rootProject.ext.has('reactNativeAndroidRoot')) {
63 | defaultDir = rootProject.ext.get('reactNativeAndroidRoot')
64 | } else {
65 | defaultDir = new File(
66 | projectDir,
67 | '/../../../node_modules/react-native/android'
68 | )
69 | }
70 |
71 | if (defaultDir.exists()) {
72 | maven {
73 | url defaultDir.toString()
74 | name androidSourcesName
75 | }
76 |
77 | logger.info(":${project.name}:reactNativeAndroidRoot ${defaultDir.canonicalPath}")
78 | found = true
79 | } else {
80 | def parentDir = rootProject.projectDir
81 |
82 | 1.upto(5, {
83 | if (found) return true
84 | parentDir = parentDir.parentFile
85 |
86 | def androidSourcesDir = new File(
87 | parentDir,
88 | 'node_modules/react-native'
89 | )
90 |
91 | def androidPrebuiltBinaryDir = new File(
92 | parentDir,
93 | 'node_modules/react-native/android'
94 | )
95 |
96 | if (androidPrebuiltBinaryDir.exists()) {
97 | maven {
98 | url androidPrebuiltBinaryDir.toString()
99 | name androidSourcesName
100 | }
101 |
102 | logger.info(":${project.name}:reactNativeAndroidRoot ${androidPrebuiltBinaryDir.canonicalPath}")
103 | found = true
104 | } else if (androidSourcesDir.exists()) {
105 | maven {
106 | url androidSourcesDir.toString()
107 | name androidSourcesName
108 | }
109 |
110 | logger.info(":${project.name}:reactNativeAndroidRoot ${androidSourcesDir.canonicalPath}")
111 | found = true
112 | }
113 | })
114 | }
115 |
116 | if (!found) {
117 | throw new GradleException(
118 | "${project.name}: unable to locate React Native android sources. " +
119 | "Ensure you have you installed React Native as a dependency in your project and try again."
120 | )
121 | }
122 | }
123 |
124 | def kotlin_version = getExtOrDefault('kotlinVersion')
125 |
126 | dependencies {
127 | // noinspection GradleDynamicVersion
128 | api 'com.facebook.react:react-native:+'
129 | implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
130 | }
131 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-native-smartconfig-quan",
3 | "version": "1.0.7",
4 | "description": "no",
5 | "main": "lib/commonjs/index",
6 | "module": "lib/module/index",
7 | "types": "lib/typescript/src/index.d.ts",
8 | "react-native": "src/index",
9 | "source": "src/index",
10 | "files": [
11 | "src",
12 | "lib",
13 | "android",
14 | "ios",
15 | "cpp",
16 | "react-native-smartconfig-quan.podspec",
17 | "!lib/typescript/example",
18 | "!**/__tests__",
19 | "!**/__fixtures__",
20 | "!**/__mocks__"
21 | ],
22 | "scripts": {
23 | "test": "jest",
24 | "typescript": "tsc --noEmit",
25 | "lint": "eslint \"**/*.{js,ts,tsx}\"",
26 | "prepare": "bob build",
27 | "release": "release-it",
28 | "example": "yarn --cwd example",
29 | "pods": "cd example && pod-install --quiet",
30 | "bootstrap": "yarn example && yarn && yarn pods"
31 | },
32 | "keywords": [
33 | "react-native-smartconfig",
34 | "smartconfig",
35 | "ESP8266"
36 | ],
37 | "repository": "https://github.com/nguyenvanquan7826/React-Native-Smart-Config-Quan",
38 | "author": "nguyenvanquan7826 (https://github.com/nguyenvanquan7826)",
39 | "license": "MIT",
40 | "bugs": {
41 | "url": "https://github.com/nguyenvanquan7826/React-Native-Smart-Config-Quan/issues"
42 | },
43 | "homepage": "https://github.com/nguyenvanquan7826/React-Native-Smart-Config-Quan#readme",
44 | "devDependencies": {
45 | "@commitlint/config-conventional": "^8.3.4",
46 | "@react-native-community/bob": "^0.16.2",
47 | "@react-native-community/eslint-config": "^2.0.0",
48 | "@release-it/conventional-changelog": "^1.1.4",
49 | "@types/jest": "^26.0.0",
50 | "@types/react": "^16.9.19",
51 | "@types/react-native": "0.62.13",
52 | "commitlint": "^8.3.5",
53 | "eslint": "^7.2.0",
54 | "eslint-config-prettier": "^6.11.0",
55 | "eslint-plugin-prettier": "^3.1.3",
56 | "husky": "^4.2.5",
57 | "jest": "^26.0.1",
58 | "pod-install": "^0.1.0",
59 | "prettier": "^2.0.5",
60 | "react": "16.11.0",
61 | "react-native": "0.62.2",
62 | "release-it": "^13.5.8",
63 | "typescript": "^3.8.3"
64 | },
65 | "peerDependencies": {
66 | "react": "*",
67 | "react-native": "*"
68 | },
69 | "jest": {
70 | "preset": "react-native",
71 | "modulePathIgnorePatterns": [
72 | "/example/node_modules",
73 | "/lib/"
74 | ]
75 | },
76 | "husky": {
77 | "hooks": {
78 | "commit-msg": "commitlint -E HUSKY_GIT_PARAMS",
79 | "pre-commit": "yarn lint && yarn typescript"
80 | }
81 | },
82 | "commitlint": {
83 | "extends": [
84 | "@commitlint/config-conventional"
85 | ]
86 | },
87 | "release-it": {
88 | "git": {
89 | "commitMessage": "chore: release ${version}",
90 | "tagName": "v${version}"
91 | },
92 | "npm": {
93 | "publish": true
94 | },
95 | "github": {
96 | "release": true
97 | },
98 | "plugins": {
99 | "@release-it/conventional-changelog": {
100 | "preset": "angular"
101 | }
102 | }
103 | },
104 | "eslintConfig": {
105 | "extends": [
106 | "@react-native-community",
107 | "prettier"
108 | ],
109 | "rules": {
110 | "prettier/prettier": [
111 | "error",
112 | {
113 | "quoteProps": "consistent",
114 | "singleQuote": true,
115 | "tabWidth": 2,
116 | "trailingComma": "es5",
117 | "useTabs": false
118 | }
119 | ]
120 | }
121 | },
122 | "eslintIgnore": [
123 | "node_modules/",
124 | "lib/"
125 | ],
126 | "prettier": {
127 | "quoteProps": "consistent",
128 | "singleQuote": true,
129 | "tabWidth": 2,
130 | "trailingComma": "es5",
131 | "useTabs": false
132 | },
133 | "@react-native-community/bob": {
134 | "source": "src",
135 | "output": "lib",
136 | "targets": [
137 | "commonjs",
138 | "module",
139 | "typescript"
140 | ]
141 | }
142 | }
143 |
--------------------------------------------------------------------------------
/ios/EspTouch/ESPTouchTask.h:
--------------------------------------------------------------------------------
1 | //
2 | // ESPTouchTask.h
3 | // EspTouchDemo
4 | //
5 | // Created by fby on 4/14/15.
6 | // Copyright (c) 2015 fby. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "ESPTouchResult.h"
11 | #import "ESPTouchDelegate.h"
12 | #import "ESPAES.h"
13 |
14 | #define ESPTOUCH_VERSION @"SDK-v1.0.0"
15 |
16 | #define DEBUG_ON YES
17 |
18 | @interface ESPTouchTask : NSObject
19 |
20 | @property (atomic,assign) BOOL isCancelled;
21 |
22 | - (id)initWithApSsid:(NSString *)apSsid andApBssid:(NSString *)apBssid andApPwd:(NSString *)apPwd andAES:(ESPAES *)aes;
23 |
24 | /**
25 | * Constructor of EsptouchTask
26 | *
27 | * @param apSsid
28 | * the Ap's ssid
29 | * @param apBssid
30 | * the Ap's bssid
31 | * @param apPwd
32 | * the Ap's password
33 | */
34 | - (id) initWithApSsid: (NSString *)apSsid andApBssid: (NSString *) apBssid andApPwd: (NSString *)apPwd;
35 |
36 | /**
37 | * Deprecated
38 | */
39 | - (id) initWithApSsid: (NSString *)apSsid andApBssid: (NSString *) apBssid andApPwd: (NSString *)apPwd andIsSsidHiden: (BOOL) isSsidHidden __deprecated_msg("Use initWithApSsid:(NSString *) andApBssid:(NSString *) andApPwd:(NSString *) instead.");
40 |
41 | /**
42 | * Constructor of EsptouchTask
43 | *
44 | * @param apSsid
45 | * the Ap's ssid
46 | * @param apBssid
47 | * the Ap's bssid
48 | * @param apPwd
49 | * the Ap's password
50 | * @param timeoutMillisecond (it should be >= 15000+6000)
51 | * millisecond of total timeout
52 | */
53 | - (id) initWithApSsid: (NSString *)apSsid andApBssid: (NSString *) apBssid andApPwd: (NSString *)apPwd andTimeoutMillisecond: (int) timeoutMillisecond;
54 |
55 | /**
56 | * Constructor of EsptouchTask
57 | *
58 | * @param apSsid
59 | * the Ap's ssid
60 | * @param apBssid
61 | * the Ap's bssid
62 | * @param apPwd
63 | * the Ap's password
64 | * @param isSsidHidden
65 | * whether the Ap's ssid is hidden
66 | * @param timeoutMillisecond (it should be >= 15000+6000)
67 | * millisecond of total timeout
68 | */
69 | - (id) initWithApSsid: (NSString *)apSsid andApBssid: (NSString *) apBssid andApPwd: (NSString *)apPwd andIsSsidHiden: (BOOL) isSsidHidden andTimeoutMillisecond: (int) timeoutMillisecond __deprecated_msg("Use initWithApSsid:(NSString *) andApBssid:(NSString *) andApPwd:(NSString *) andTimeoutMillisecond:(int) instead.");
70 |
71 | /**
72 | * Interrupt the Esptouch Task when User tap back or close the Application.
73 | */
74 | - (void) interrupt;
75 |
76 | /**
77 | * Note: !!!Don't call the task at UI Main Thread
78 | *
79 | * Smart Config v2.4 support the API
80 | *
81 | * @return the ESPTouchResult
82 | */
83 | - (ESPTouchResult*) executeForResult;
84 |
85 | /**
86 | * Note: !!!Don't call the task at UI Main Thread
87 | *
88 | * Smart Config v2.4 support the API
89 | *
90 | * It will be blocked until the client receive result count >= expectTaskResultCount.
91 | * If it fail, it will return one fail result will be returned in the list.
92 | * If it is cancelled while executing,
93 | * if it has received some results, all of them will be returned in the list.
94 | * if it hasn't received any results, one cancel result will be returned in the list.
95 | *
96 | * @param expectTaskResultCount
97 | * the expect result count(if expectTaskResultCount <= 0,
98 | * expectTaskResultCount = INT32_MAX)
99 | * @return the NSArray of EsptouchResult
100 | * @throws RuntimeException
101 | */
102 | - (NSArray*) executeForResults:(int) expectTaskResultCount;
103 |
104 | /**
105 | * set the esptouch delegate, when one device is connected to the Ap, it will be called back
106 | * @param esptouchDelegate when one device is connected to the Ap, it will be called back
107 | */
108 | - (void) setEsptouchDelegate: (NSObject *) esptouchDelegate;
109 |
110 | /**
111 | * Set boradcast or multicast when post config info
112 | * @param broadcast YES is boradcast, NO is multicast
113 | */
114 | - (void) setPackageBroadcast: (BOOL) broadcast;
115 | @end
116 |
--------------------------------------------------------------------------------
/android/src/main/java/esptouch/EsptouchTask.java:
--------------------------------------------------------------------------------
1 | package esptouch;
2 |
3 | import android.content.Context;
4 | import android.text.TextUtils;
5 |
6 | import java.util.List;
7 |
8 | import esptouch.protocol.TouchData;
9 | import esptouch.task.EsptouchTaskParameter;
10 | import esptouch.task.__EsptouchTask;
11 | import esptouch.util.EspAES;
12 | import esptouch.util.TouchNetUtil;
13 |
14 | public class EsptouchTask implements IEsptouchTask {
15 | private __EsptouchTask _mEsptouchTask;
16 | private EsptouchTaskParameter _mParameter;
17 |
18 | /**
19 | * Constructor of EsptouchTask
20 | *
21 | * @param apSsid the Ap's ssid
22 | * @param apBssid the Ap's bssid
23 | * @param apPassword the Ap's password
24 | * @param context the {@link Context} of the Application
25 | */
26 | public EsptouchTask(String apSsid, String apBssid, String apPassword, Context context) {
27 | this(apSsid, apBssid, apPassword, null, context);
28 | }
29 |
30 | /**
31 | * Constructor of EsptouchTask
32 | *
33 | * @param apSsid the Ap's ssid
34 | * @param apBssid the Ap's bssid
35 | * @param apPassword the Ap's password
36 | * @param context the {@link Context} of the Application
37 | */
38 | public EsptouchTask(byte[] apSsid, byte[] apBssid, byte[] apPassword, Context context) {
39 | this(apSsid, apBssid, apPassword, null, context);
40 | }
41 |
42 | private EsptouchTask(String apSsid, String apBssid, String apPassword, EspAES espAES, Context context) {
43 | if (TextUtils.isEmpty(apSsid)) {
44 | throw new NullPointerException("SSID can't be empty");
45 | }
46 | if (TextUtils.isEmpty(apBssid)) {
47 | throw new NullPointerException("BSSID can't be empty");
48 | }
49 | if (apPassword == null) {
50 | apPassword = "";
51 | }
52 | TouchData ssid = new TouchData(apSsid);
53 | TouchData bssid = new TouchData(TouchNetUtil.parseBssid2bytes(apBssid));
54 | TouchData password = new TouchData(apPassword);
55 | init(context, ssid, bssid, password, espAES);
56 | }
57 |
58 | private EsptouchTask(byte[] apSsid, byte[] apBssid, byte[] apPassword, EspAES espAES, Context context) {
59 | if (apSsid == null || apSsid.length == 0) {
60 | throw new NullPointerException("SSID can't be empty");
61 | }
62 | if (apBssid == null || apBssid.length == 0) {
63 | throw new NullPointerException("BSSID can't be empty");
64 | }
65 | if (apPassword == null) {
66 | apPassword = new byte[0];
67 | }
68 | TouchData ssid = new TouchData(apSsid);
69 | TouchData bssid = new TouchData(apBssid);
70 | TouchData password = new TouchData(apPassword);
71 | init(context, ssid, bssid, password, espAES);
72 | }
73 |
74 | private void init(Context context, TouchData ssid, TouchData bssid, TouchData password, EspAES aes) {
75 | _mParameter = new EsptouchTaskParameter();
76 | _mEsptouchTask = new __EsptouchTask(context, ssid, bssid, password, aes, _mParameter, true);
77 | }
78 |
79 | @Override
80 | public void interrupt() {
81 | _mEsptouchTask.interrupt();
82 | }
83 |
84 | @Override
85 | public IEsptouchResult executeForResult() throws RuntimeException {
86 | return _mEsptouchTask.executeForResult();
87 | }
88 |
89 | @Override
90 | public boolean isCancelled() {
91 | return _mEsptouchTask.isCancelled();
92 | }
93 |
94 | @Override
95 | public List executeForResults(int expectTaskResultCount)
96 | throws RuntimeException {
97 | if (expectTaskResultCount <= 0) {
98 | expectTaskResultCount = Integer.MAX_VALUE;
99 | }
100 | return _mEsptouchTask.executeForResults(expectTaskResultCount);
101 | }
102 |
103 | @Override
104 | public void setEsptouchListener(IEsptouchListener esptouchListener) {
105 | _mEsptouchTask.setEsptouchListener(esptouchListener);
106 | }
107 |
108 | @Override
109 | public void setPackageBroadcast(boolean broadcast) {
110 | _mParameter.setBroadcast(broadcast);
111 | }
112 | }
113 |
--------------------------------------------------------------------------------
/android/src/main/java/esptouch/util/TouchNetUtil.java:
--------------------------------------------------------------------------------
1 | package esptouch.util;
2 |
3 | import android.content.Context;
4 | import android.net.wifi.WifiInfo;
5 | import android.net.wifi.WifiManager;
6 |
7 | import java.lang.reflect.InvocationTargetException;
8 | import java.lang.reflect.Method;
9 | import java.net.InetAddress;
10 | import java.net.UnknownHostException;
11 |
12 | public class TouchNetUtil {
13 |
14 | /**
15 | * get the local ip address by Android System
16 | *
17 | * @param context the context
18 | * @return the local ip addr allocated by Ap
19 | */
20 | public static InetAddress getLocalInetAddress(Context context) {
21 | WifiManager wm = (WifiManager) context
22 | .getSystemService(Context.WIFI_SERVICE);
23 | WifiInfo wifiInfo = wm.getConnectionInfo();
24 | int localAddrInt = wifiInfo.getIpAddress();
25 | String localAddrStr = __formatString(localAddrInt);
26 | InetAddress localInetAddr = null;
27 | try {
28 | localInetAddr = InetAddress.getByName(localAddrStr);
29 | } catch (UnknownHostException e) {
30 | e.printStackTrace();
31 | }
32 | return localInetAddr;
33 | }
34 |
35 | private static String __formatString(int value) {
36 | String strValue = "";
37 | byte[] ary = __intToByteArray(value);
38 | for (int i = ary.length - 1; i >= 0; i--) {
39 | strValue += (ary[i] & 0xFF);
40 | if (i > 0) {
41 | strValue += ".";
42 | }
43 | }
44 | return strValue;
45 | }
46 |
47 | private static byte[] __intToByteArray(int value) {
48 | byte[] b = new byte[4];
49 | for (int i = 0; i < 4; i++) {
50 | int offset = (b.length - 1 - i) * 8;
51 | b[i] = (byte) ((value >>> offset) & 0xFF);
52 | }
53 | return b;
54 | }
55 |
56 | /**
57 | * parse InetAddress
58 | *
59 | * @param inetAddrBytes
60 | * @return
61 | */
62 | public static InetAddress parseInetAddr(byte[] inetAddrBytes, int offset,
63 | int count) {
64 | InetAddress inetAddress = null;
65 | StringBuilder sb = new StringBuilder();
66 | for (int i = 0; i < count; i++) {
67 | sb.append(Integer.toString(inetAddrBytes[offset + i] & 0xff));
68 | if (i != count - 1) {
69 | sb.append('.');
70 | }
71 | }
72 | try {
73 | inetAddress = InetAddress.getByName(sb.toString());
74 | } catch (UnknownHostException e) {
75 | e.printStackTrace();
76 | }
77 | return inetAddress;
78 | }
79 |
80 | /**
81 | * parse bssid
82 | *
83 | * @param bssid the bssid like aa:bb:cc:dd:ee:ff
84 | * @return byte converted from bssid
85 | */
86 | public static byte[] parseBssid2bytes(String bssid) {
87 | String bssidSplits[] = bssid.split(":");
88 | byte[] result = new byte[bssidSplits.length];
89 | for (int i = 0; i < bssidSplits.length; i++) {
90 | result[i] = (byte) Integer.parseInt(bssidSplits[i], 16);
91 | }
92 | return result;
93 | }
94 |
95 | public static byte[] getOriginalSsidBytes(WifiInfo info) {
96 | try {
97 | Method method = info.getClass().getMethod("getWifiSsid");
98 | if (method == null) {
99 | return null;
100 | }
101 | method.setAccessible(true);
102 | Object wifiSsid = method.invoke(info);
103 | if (wifiSsid == null) {
104 | return null;
105 | }
106 | method = wifiSsid.getClass().getMethod("getOctets");
107 | if (method == null) {
108 | return null;
109 | }
110 | method.setAccessible(true);
111 | return (byte[]) method.invoke(wifiSsid);
112 | } catch (NoSuchMethodException e) {
113 | e.printStackTrace();
114 | } catch (IllegalAccessException e) {
115 | e.printStackTrace();
116 | } catch (InvocationTargetException e) {
117 | e.printStackTrace();
118 | } catch (NullPointerException e) {
119 | e.printStackTrace();
120 | }
121 | return null;
122 | }
123 | }
124 |
--------------------------------------------------------------------------------
/example/ios/SmartconfigSwjavaExample.xcodeproj/xcshareddata/xcschemes/SmartconfigSwjavaExample.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
29 |
35 |
36 |
37 |
38 |
39 |
44 |
45 |
51 |
52 |
53 |
54 |
64 |
66 |
72 |
73 |
74 |
75 |
81 |
83 |
89 |
90 |
91 |
92 |
94 |
95 |
98 |
99 |
100 |
--------------------------------------------------------------------------------
/android/src/main/java/esptouch/udp/UDPSocketClient.java:
--------------------------------------------------------------------------------
1 | package esptouch.udp;
2 |
3 | import android.util.Log;
4 |
5 | import java.io.IOException;
6 | import java.net.DatagramPacket;
7 | import java.net.DatagramSocket;
8 | import java.net.InetAddress;
9 | import java.net.SocketException;
10 | import java.net.UnknownHostException;
11 |
12 | import esptouch.task.__IEsptouchTask;
13 |
14 | /**
15 | * this class is used to help send UDP data according to length
16 | *
17 | * @author afunx
18 | */
19 | public class UDPSocketClient {
20 |
21 | private static final String TAG = "UDPSocketClient";
22 | private DatagramSocket mSocket;
23 | private volatile boolean mIsStop;
24 | private volatile boolean mIsClosed;
25 |
26 | public UDPSocketClient() {
27 | try {
28 | this.mSocket = new DatagramSocket();
29 | this.mIsStop = false;
30 | this.mIsClosed = false;
31 | } catch (SocketException e) {
32 | if (__IEsptouchTask.DEBUG) {
33 | Log.w(TAG, "SocketException");
34 | }
35 | e.printStackTrace();
36 | }
37 | }
38 |
39 | @Override
40 | protected void finalize() throws Throwable {
41 | close();
42 | super.finalize();
43 | }
44 |
45 | public void interrupt() {
46 | if (__IEsptouchTask.DEBUG) {
47 | Log.i(TAG, "USPSocketClient is interrupt");
48 | }
49 | this.mIsStop = true;
50 | }
51 |
52 | /**
53 | * close the UDP socket
54 | */
55 | public synchronized void close() {
56 | if (!this.mIsClosed) {
57 | this.mSocket.close();
58 | this.mIsClosed = true;
59 | }
60 | }
61 |
62 | /**
63 | * send the data by UDP
64 | *
65 | * @param data the data to be sent
66 | * @param targetPort the port of target
67 | * @param interval the milliseconds to between each UDP sent
68 | */
69 | public void sendData(byte[][] data, String targetHostName, int targetPort,
70 | long interval) {
71 | sendData(data, 0, data.length, targetHostName, targetPort, interval);
72 | }
73 |
74 |
75 | /**
76 | * send the data by UDP
77 | *
78 | * @param data the data to be sent
79 | * @param offset the offset which data to be sent
80 | * @param count the count of the data
81 | * @param targetPort the port of target
82 | * @param interval the milliseconds to between each UDP sent
83 | */
84 | public void sendData(byte[][] data, int offset, int count,
85 | String targetHostName, int targetPort, long interval) {
86 | if ((data == null) || (data.length <= 0)) {
87 | if (__IEsptouchTask.DEBUG) {
88 | Log.w(TAG, "sendData(): data == null or length <= 0");
89 | }
90 | return;
91 | }
92 | for (int i = offset; !mIsStop && i < offset + count; i++) {
93 | if (data[i].length == 0) {
94 | continue;
95 | }
96 | try {
97 | InetAddress targetInetAddress = InetAddress.getByName(targetHostName);
98 | DatagramPacket localDatagramPacket = new DatagramPacket(
99 | data[i], data[i].length, targetInetAddress, targetPort);
100 | this.mSocket.send(localDatagramPacket);
101 | } catch (UnknownHostException e) {
102 | if (__IEsptouchTask.DEBUG) {
103 | Log.w(TAG, "sendData(): UnknownHostException");
104 | }
105 | e.printStackTrace();
106 | mIsStop = true;
107 | break;
108 | } catch (IOException e) {
109 | if (__IEsptouchTask.DEBUG) {
110 | Log.w(TAG, "sendData(): IOException, but just ignore it");
111 | }
112 | // for the Ap will make some troubles when the phone send too many UDP packets,
113 | // but we don't expect the UDP packet received by others, so just ignore it
114 | }
115 | try {
116 | Thread.sleep(interval);
117 | } catch (InterruptedException e) {
118 | e.printStackTrace();
119 | if (__IEsptouchTask.DEBUG) {
120 | Log.w(TAG, "sendData is Interrupted");
121 | }
122 | mIsStop = true;
123 | break;
124 | }
125 | }
126 | if (mIsStop) {
127 | close();
128 | }
129 | }
130 | }
131 |
--------------------------------------------------------------------------------
/ios/EspTouch/ESPUtils/ESP_ByteUtil.m:
--------------------------------------------------------------------------------
1 | //
2 | // ESP_ByteUtil.m
3 | // EspTouchDemo
4 | //
5 | // Created by fby on 4/7/15.
6 | // Copyright (c) 2015 fby. All rights reserved.
7 | //
8 |
9 | #import "ESP_ByteUtil.h"
10 |
11 | @implementation ESP_ByteUtil
12 |
13 | + (Byte) convertUint8toByte:(char) uint8
14 | {
15 | return (Byte)uint8;
16 | }
17 |
18 | + (UInt8) convertByte2Uint8:(Byte) b
19 | {
20 | return (UInt8) (b & 0xff);
21 | }
22 |
23 | + (NSString *) convertByte2HexString:(Byte) b
24 | {
25 | UInt8 u8 = [self convertByte2Uint8:b];
26 | return [NSString stringWithFormat:@"%x",u8];
27 | }
28 |
29 | + (unsigned int)intFromHexString:(NSString *) hexStr
30 | {
31 | unsigned int hexInt = 0;
32 |
33 | // Create scanner
34 | NSScanner *scanner = [NSScanner scannerWithString:hexStr];
35 |
36 | // Tell scanner to skip the # character
37 | // [scanner setCharactersToBeSkipped:[NSCharacterSet characterSetWithCharactersInString:@"#"]];
38 |
39 | // Scan hex value
40 | [scanner scanHexInt:&hexInt];
41 |
42 | return hexInt;
43 | }
44 |
45 | + (NSData *) splitUint8To2Bytes: (UInt8) uint8
46 | {
47 | NSString *hexString = [NSString stringWithFormat:@"%x",uint8];
48 | Byte low;
49 | Byte high;
50 | if (hexString.length > 1)
51 | {
52 | high = [self intFromHexString:[hexString substringWithRange:NSMakeRange(0, 1)]];
53 | low =[self intFromHexString:[hexString substringWithRange:NSMakeRange(1, 1)]];
54 | }
55 | else
56 | {
57 | high = 0;
58 | low = [self intFromHexString:[hexString substringWithRange:NSMakeRange(0, 1)]];
59 | }
60 |
61 | Byte bytes[] = { high, low };
62 | NSData *data = [[NSData alloc] initWithBytes:bytes length:2];
63 | return data;
64 | }
65 |
66 | + (Byte) combine2bytesToOneWithHigh: (Byte) high andLow: (Byte) low
67 | {
68 | return (Byte) (high << 4 | low);
69 | }
70 |
71 | + (UInt16) combine2bytesToU16WithHigh: (Byte) high andLow: (Byte) low
72 | {
73 | UInt8 highU8 = [self convertByte2Uint8:high];
74 | UInt8 lowU8 = [self convertByte2Uint8:low];
75 | return (highU8 << 8 | lowU8);
76 | }
77 |
78 | + (Byte) randomByte
79 | {
80 | return arc4random() % 256;
81 | }
82 |
83 | + (NSData *) randomBytes: (UInt8) len
84 | {
85 | Byte bytes[len];
86 | for (int i = 0; i < len; i++) {
87 | bytes[i] = [self randomByte];
88 | }
89 | NSData *data = [[NSData alloc]initWithBytes:bytes length:len];
90 | return data;
91 | }
92 |
93 | + (NSData *) genSpecBytesWithU16:(UInt16)len
94 | {
95 | Byte bytes[len];
96 | for (int i = 0; i < len; i++) {
97 | bytes[i] = '1';
98 | }
99 | NSData *data = [[NSData alloc]initWithBytes:bytes length:len];
100 | return data;
101 | }
102 |
103 | + (NSData *) genSpecBytesWithU8:(Byte) len
104 | {
105 | UInt8 u8 = [self convertByte2Uint8:len];
106 | return [self genSpecBytesWithU16:u8];
107 | }
108 |
109 | + (NSString *) parseBssid:(Byte[]) bssidBytes Offset: (int) offset Count: (int) count
110 | {
111 | Byte bytes[count];
112 | for (int i = 0; i < count; i++ )
113 | {
114 | bytes[i] = bssidBytes[i + offset];
115 | }
116 | return [self parseBssid:bytes Len:count];
117 | }
118 |
119 | + (NSString *) parseBssid:(Byte[]) bssidBytes Len:(int)len
120 | {
121 | NSMutableString *mStr = [[NSMutableString alloc]init];
122 | int k;
123 | NSString* hexK;
124 | NSString* str;
125 | for (int i = 0; i < len; i++)
126 | {
127 | k = 0xff & bssidBytes[i];
128 | hexK = [NSString stringWithFormat:@"%x", k];
129 | str = ((k < 16) ? ([NSString stringWithFormat:@"0%@",hexK ]) : (hexK));
130 | [mStr appendString:str];
131 | }
132 | return mStr;
133 | }
134 |
135 | + (NSData *) getBytesByNSString: (NSString *)string
136 | {
137 | NSUInteger numberOfBytes = [string lengthOfBytesUsingEncoding:ESPTOUCH_NSStringEncoding];
138 | Byte bytes[numberOfBytes];
139 | NSRange range = NSMakeRange(0, numberOfBytes);
140 | [string getBytes:bytes maxLength:numberOfBytes usedLength:nil encoding:ESPTOUCH_NSStringEncoding options:0 range:range remainingRange:NULL];
141 | NSData *data = [[NSData alloc]initWithBytes:bytes length:numberOfBytes];
142 | return data;
143 | }
144 |
145 | + (NSString *) getHexStringByData:(NSData *)data
146 | {
147 | NSMutableString* mStr = [[NSMutableString alloc]init];
148 | NSUInteger totalLen = [data length];
149 | Byte bytes[totalLen];
150 | [data getBytes:&bytes length:totalLen];
151 | for (int i = 0; i < totalLen; i++)
152 | {
153 | NSString *hexString = [[NSString alloc]initWithFormat:@"0x%.2x ",bytes[i]];
154 | [mStr appendString:hexString];
155 | }
156 | return mStr;
157 | }
158 |
159 | @end
160 |
--------------------------------------------------------------------------------
/android/src/main/java/esptouch/task/IEsptouchTaskParameter.java:
--------------------------------------------------------------------------------
1 | package esptouch.task;
2 |
3 | public interface IEsptouchTaskParameter {
4 |
5 | /**
6 | * get interval millisecond for guide code(the timeText between each guide code sending)
7 | *
8 | * @return interval millisecond for guide code(the timeText between each guide code sending)
9 | */
10 | long getIntervalGuideCodeMillisecond();
11 |
12 | /**
13 | * get interval millisecond for data code(the timeText between each data code sending)
14 | *
15 | * @return interval millisecond for data code(the timeText between each data code sending)
16 | */
17 | long getIntervalDataCodeMillisecond();
18 |
19 | /**
20 | * get timeout millisecond for guide code(the timeText how much the guide code sending)
21 | *
22 | * @return timeout millisecond for guide code(the timeText how much the guide code sending)
23 | */
24 | long getTimeoutGuideCodeMillisecond();
25 |
26 | /**
27 | * get timeout millisecond for data code(the timeText how much the data code sending)
28 | *
29 | * @return timeout millisecond for data code(the timeText how much the data code sending)
30 | */
31 | long getTimeoutDataCodeMillisecond();
32 |
33 | /**
34 | * get timeout millisecond for total code(guide code and data code altogether)
35 | *
36 | * @return timeout millisecond for total code(guide code and data code altogether)
37 | */
38 | long getTimeoutTotalCodeMillisecond();
39 |
40 | /**
41 | * get total repeat timeText for executing esptouch task
42 | *
43 | * @return total repeat timeText for executing esptouch task
44 | */
45 | int getTotalRepeatTime();
46 |
47 | /**
48 | * the length of the Esptouch result 1st byte is the total length of ssid and
49 | * password, the other 6 bytes are the device's bssid
50 | */
51 |
52 | /**
53 | * get esptouchResult length of one
54 | *
55 | * @return length of one
56 | */
57 | int getEsptouchResultOneLen();
58 |
59 | /**
60 | * get esptouchResult length of mac
61 | *
62 | * @return length of mac
63 | */
64 | int getEsptouchResultMacLen();
65 |
66 | /**
67 | * get esptouchResult length of ip
68 | *
69 | * @return length of ip
70 | */
71 | int getEsptouchResultIpLen();
72 |
73 | /**
74 | * get esptouchResult total length
75 | *
76 | * @return total length
77 | */
78 | int getEsptouchResultTotalLen();
79 |
80 | /**
81 | * get port for listening(used by server)
82 | *
83 | * @return port for listening(used by server)
84 | */
85 | int getPortListening();
86 |
87 | /**
88 | * get target hostname
89 | *
90 | * @return target hostame(used by client)
91 | */
92 | String getTargetHostname();
93 |
94 | /**
95 | * get target port
96 | *
97 | * @return target port(used by client)
98 | */
99 | int getTargetPort();
100 |
101 | /**
102 | * get millisecond for waiting udp receiving(receiving without sending)
103 | *
104 | * @return millisecond for waiting udp receiving(receiving without sending)
105 | */
106 | int getWaitUdpReceivingMillisecond();
107 |
108 | /**
109 | * get millisecond for waiting udp sending(sending including receiving)
110 | *
111 | * @return millisecond for waiting udep sending(sending including receiving)
112 | */
113 | int getWaitUdpSendingMillisecond();
114 |
115 | /**
116 | * get millisecond for waiting udp sending and receiving
117 | *
118 | * @return millisecond for waiting udp sending and receiving
119 | */
120 | int getWaitUdpTotalMillisecond();
121 |
122 | /**
123 | * set the millisecond for waiting udp sending and receiving
124 | *
125 | * @param waitUdpTotalMillisecond the millisecond for waiting udp sending and receiving
126 | */
127 | void setWaitUdpTotalMillisecond(int waitUdpTotalMillisecond);
128 |
129 | /**
130 | * get the threshold for how many correct broadcast should be received
131 | *
132 | * @return the threshold for how many correct broadcast should be received
133 | */
134 | int getThresholdSucBroadcastCount();
135 |
136 | /**
137 | * get the count of expect task results
138 | *
139 | * @return the count of expect task results
140 | */
141 | int getExpectTaskResultCount();
142 |
143 | /**
144 | * set the count of expect task results
145 | *
146 | * @param expectTaskResultCount the count of expect task results
147 | */
148 | void setExpectTaskResultCount(int expectTaskResultCount);
149 |
150 | /**
151 | * Set broadcast or multicast
152 | *
153 | * @param broadcast true is broadcast, false is multicast
154 | */
155 | void setBroadcast(boolean broadcast);
156 | }
157 |
--------------------------------------------------------------------------------
/ios/EspTouch/task/ESPTouchTaskParameter.h:
--------------------------------------------------------------------------------
1 | //
2 | // ESPTaskParameter.h
3 | // EspTouchDemo
4 | //
5 | // Created by fby on 5/20/15.
6 | // Copyright (c) 2015 fby. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface ESPTaskParameter : NSObject
12 |
13 | /**
14 | * get interval millisecond for guide code(the time between each guide code sending)
15 | * @return interval millisecond for guide code(the time between each guide code sending)
16 | */
17 | - (long) getIntervalGuideCodeMillisecond;
18 |
19 | /**
20 | * get interval millisecond for data code(the time between each data code sending)
21 | * @return interval millisecond for data code(the time between each data code sending)
22 | */
23 | - (long) getIntervalDataCodeMillisecond;
24 |
25 | /**
26 | * get timeout millisecond for guide code(the time how much the guide code sending)
27 | * @return timeout millisecond for guide code(the time how much the guide code sending)
28 | */
29 | - (long) getTimeoutGuideCodeMillisecond;
30 |
31 | /**
32 | * get timeout millisecond for data code(the time how much the data code sending)
33 | * @return timeout millisecond for data code(the time how much the data code sending)
34 | */
35 | - (long) getTimeoutDataCodeMillisecond;
36 |
37 | /**
38 | * get timeout millisecond for total code(guide code and data code altogether)
39 | * @return timeout millisecond for total code(guide code and data code altogether)
40 | */
41 | - (long) getTimeoutTotalCodeMillisecond;
42 |
43 | /**
44 | * get total repeat time for executing esptouch task
45 | * @return total repeat time for executing esptouch task
46 | */
47 | - (int) getTotalRepeatTime;
48 |
49 | /**
50 | * the length of the Esptouch result 1st byte is the total length of ssid and
51 | * password, the other 6 bytes are the device's bssid
52 | */
53 |
54 | /**
55 | * get esptouchResult length of one
56 | * @return length of one
57 | */
58 | - (int) getEsptouchResultOneLen;
59 |
60 | /**
61 | * get esptouchResult length of mac
62 | * @return length of mac
63 | */
64 | - (int) getEsptouchResultMacLen;
65 |
66 | /**
67 | * get esptouchResult length of ip
68 | * @return length of ip
69 | */
70 | - (int) getEsptouchResultIpLen;
71 |
72 | /**
73 | * get esptouchResult total length
74 | * @return total length
75 | */
76 | - (int) getEsptouchResultTotalLen;
77 |
78 | /**
79 | * get port for listening(used by server)
80 | * @return port for listening(used by server)
81 | */
82 | - (int) getPortListening;
83 |
84 | /**
85 | * get target hostname
86 | * @return target hostame(used by client)
87 | */
88 | - (NSString *) getTargetHostname;
89 |
90 | /**
91 | * get target port
92 | * @return target port(used by client)
93 | */
94 | - (int) getTargetPort;
95 |
96 | /**
97 | * get millisecond for waiting udp receiving(receiving without sending)
98 | * @return millisecond for waiting udp receiving(receiving without sending)
99 | */
100 | - (int) getWaitUdpReceivingMillisecond;
101 |
102 | /**
103 | * get millisecond for waiting udp sending(sending including receiving)
104 | * @return millisecond for waiting udep sending(sending including receiving)
105 | */
106 | - (int) getWaitUdpSendingMillisecond;
107 |
108 | /**
109 | * get millisecond for waiting udp sending and receiving
110 | * @return millisecond for waiting udp sending and receiving
111 | */
112 | - (int) getWaitUdpTotalMillisecond;
113 |
114 | /**
115 | * get the threshold for how many correct broadcast should be received
116 | * @return the threshold for how many correct broadcast should be received
117 | */
118 | - (int) getThresholdSucBroadcastCount;
119 |
120 | /**
121 | * set the millisecond for waiting udp sending and receiving
122 | * @param waitUdpTotalMillisecond the millisecond for waiting udp sending and receiving
123 | */
124 | - (void) setWaitUdpTotalMillisecond: (int) waitUdpTotalMillisecond;
125 |
126 |
127 | /**
128 | * get the count of expect task results
129 | * @return the count of expect task results
130 | */
131 | - (int) getExpectTaskResultCount;
132 |
133 | /**
134 | * set the count of expect task results
135 | * @param expectTaskResultCount the count of expect task results
136 | */
137 | - (void) setExpectTaskResultCount: (int) expectTaskResultCount;
138 |
139 | /**
140 | * get whether the router support IPv4
141 | * @return whether the router support IPv4
142 | */
143 | - (BOOL) isIPv4Supported;
144 |
145 | /**
146 | * set whether the router support IPv4
147 | * @param isIPv4Supported whether the router support IPv4
148 | */
149 | - (void) setIsIPv4Supported:(BOOL) isIPv4Supported;
150 |
151 | /**
152 | * get whether the router support IPv6
153 | * @return whether the router support IPv6
154 | */
155 | - (BOOL) isIPv6Supported;
156 |
157 | /**
158 | * set whether the router support IPv6
159 | * @param isIPv6Supported whether the router support IPv6
160 | */
161 | - (void) setIsIPv6Supported:(BOOL) isIPv6Supported;
162 |
163 | /**
164 | * set listening port for IPv6
165 | */
166 | - (void) setListeningPort6:(int) listeningPort6;
167 |
168 | /**
169 | * Set broadcast or multicast
170 | */
171 | - (void) setBroadcast:(BOOL) broadcast;
172 |
173 | @end
174 |
--------------------------------------------------------------------------------
/android/src/main/java/esptouch/udp/UDPSocketServer.java:
--------------------------------------------------------------------------------
1 | package esptouch.udp;
2 |
3 | import android.content.Context;
4 | import android.net.wifi.WifiManager;
5 | import android.util.Log;
6 |
7 | import java.io.IOException;
8 | import java.net.DatagramPacket;
9 | import java.net.DatagramSocket;
10 | import java.net.InetSocketAddress;
11 | import java.net.SocketException;
12 | import java.util.Arrays;
13 |
14 | public class UDPSocketServer {
15 | private static final String TAG = "UDPSocketServer";
16 | private DatagramSocket mServerSocket;
17 | private Context mContext;
18 | private WifiManager.MulticastLock mLock;
19 | private volatile boolean mIsClosed;
20 |
21 | /**
22 | * Constructor of UDP Socket Server
23 | *
24 | * @param port the Socket Server port
25 | * @param socketTimeout the socket read timeout
26 | * @param context the context of the Application
27 | */
28 | public UDPSocketServer(int port, int socketTimeout, Context context) {
29 | this.mContext = context;
30 | try {
31 | this.mServerSocket = new DatagramSocket(null);
32 | this.mServerSocket.setReuseAddress(true);
33 | this.mServerSocket.bind(new InetSocketAddress(port));
34 | this.mServerSocket.setSoTimeout(socketTimeout);
35 | } catch (IOException e) {
36 | Log.w(TAG, "IOException");
37 | e.printStackTrace();
38 | }
39 | this.mIsClosed = false;
40 | WifiManager manager = (WifiManager) mContext.getApplicationContext()
41 | .getSystemService(Context.WIFI_SERVICE);
42 | mLock = manager.createMulticastLock("test wifi");
43 | Log.d(TAG, "mServerSocket is created, socket read timeout: "
44 | + socketTimeout + ", port: " + port);
45 | }
46 |
47 | private synchronized void acquireLock() {
48 | if (mLock != null && !mLock.isHeld()) {
49 | mLock.acquire();
50 | }
51 | }
52 |
53 | private synchronized void releaseLock() {
54 | if (mLock != null && mLock.isHeld()) {
55 | try {
56 | mLock.release();
57 | } catch (Throwable th) {
58 | // ignoring this exception, probably wakeLock was already released
59 | }
60 | }
61 | }
62 |
63 | /**
64 | * Set the socket timeout in milliseconds
65 | *
66 | * @param timeout the timeout in milliseconds or 0 for no timeout.
67 | * @return true whether the timeout is set suc
68 | */
69 | public boolean setSoTimeout(int timeout) {
70 | try {
71 | this.mServerSocket.setSoTimeout(timeout);
72 | return true;
73 | } catch (SocketException e) {
74 | e.printStackTrace();
75 | }
76 | return false;
77 | }
78 |
79 | /**
80 | * Receive one byte from the port and convert it into String
81 | *
82 | * @return
83 | */
84 | public byte receiveOneByte() {
85 | Log.d(TAG, "receiveOneByte() entrance");
86 | try {
87 | acquireLock();
88 | DatagramPacket packet = new DatagramPacket(new byte[1], 1);
89 | mServerSocket.receive(packet);
90 | Log.d(TAG, "receive: " + (packet.getData()[0]));
91 | return packet.getData()[0];
92 | } catch (Exception e) {
93 | e.printStackTrace();
94 | }
95 | return -1;
96 | }
97 |
98 | /**
99 | * Receive specific length bytes from the port and convert it into String
100 | * 21,24,-2,52,-102,-93,-60
101 | * 15,18,fe,34,9a,a3,c4
102 | *
103 | * @return
104 | */
105 | public byte[] receiveSpecLenBytes(int len) {
106 | Log.d(TAG, "receiveSpecLenBytes() entrance: len = " + len);
107 | try {
108 | acquireLock();
109 | DatagramPacket packet = new DatagramPacket(new byte[64], 64);
110 | mServerSocket.receive(packet);
111 | byte[] recDatas = Arrays.copyOf(packet.getData(), packet.getLength());
112 | Log.d(TAG, "received len : " + recDatas.length);
113 | for (int i = 0; i < recDatas.length; i++) {
114 | Log.w(TAG, "recDatas[" + i + "]:" + recDatas[i]);
115 | }
116 | Log.w(TAG, "receiveSpecLenBytes: " + new String(recDatas));
117 | if (recDatas.length != len) {
118 | Log.w(TAG,
119 | "received len is different from specific len, return null");
120 | return null;
121 | }
122 | return recDatas;
123 | } catch (Exception e) {
124 | e.printStackTrace();
125 | }
126 | return null;
127 | }
128 |
129 | public void interrupt() {
130 | Log.i(TAG, "USPSocketServer is interrupt");
131 | close();
132 | }
133 |
134 | public synchronized void close() {
135 | if (!this.mIsClosed) {
136 | Log.w(TAG, "mServerSocket is closed");
137 | mServerSocket.close();
138 | releaseLock();
139 | this.mIsClosed = true;
140 | }
141 | }
142 |
143 | @Override
144 | protected void finalize() throws Throwable {
145 | close();
146 | super.finalize();
147 | }
148 |
149 | }
150 |
--------------------------------------------------------------------------------
/ios/EspTouch/ESPUtils/ESPTools.m:
--------------------------------------------------------------------------------
1 | //
2 | // EspNetUtils.m
3 | // Esp32Mesh
4 | //
5 | // Created by AE on 2018/4/19.
6 | // Copyright © 2018年 AE. All rights reserved.
7 | //
8 |
9 | #import "ESPTools.h"
10 | #import
11 | #import
12 | #import
13 | #import
14 |
15 | #define IOS_CELLULAR @"pdp_ip0"
16 | #define IOS_WIFI @"en0"
17 | #define IOS_VPN @"utun0"
18 | #define IP_ADDR_IPv4 @"ipv4"
19 | #define IP_ADDR_IPv6 @"ipv6"
20 |
21 | @implementation ESPTools
22 |
23 | + (nullable NSString *)getCurrentWiFiSsid {
24 | NSArray *ifs = (__bridge_transfer id)CNCopySupportedInterfaces();
25 | id info = nil;
26 | for (NSString *ifnam in ifs) {
27 | info = (__bridge_transfer id)CNCopyCurrentNetworkInfo((__bridge CFStringRef)ifnam);
28 | if (info && [info count]) {
29 | break;
30 | }
31 | }
32 | // Key: BSSID, SSID, SSIDDATA
33 | return [(NSDictionary*)info objectForKey:@"SSID"];
34 | }
35 |
36 | + (nullable NSString *)getCurrentBSSID {
37 | NSArray *ifs = (__bridge_transfer id)CNCopySupportedInterfaces();
38 | id info = nil;
39 | for (NSString *ifnam in ifs) {
40 | info = (__bridge_transfer id)CNCopyCurrentNetworkInfo((__bridge CFStringRef)ifnam);
41 | if (info && [info count]) {
42 | break;
43 | }
44 | }
45 | // Key: BSSID, SSID, SSIDDATA
46 | return [(NSDictionary*)info objectForKey:@"BSSID"];
47 | }
48 |
49 | + (NSString *)getIPAddress:(BOOL)preferIPv4 {
50 | NSArray *searchArray = preferIPv4 ?
51 | @[ IOS_VPN @"/" IP_ADDR_IPv4, IOS_VPN @"/" IP_ADDR_IPv6, IOS_WIFI @"/" IP_ADDR_IPv4, IOS_WIFI @"/" IP_ADDR_IPv6, IOS_CELLULAR @"/" IP_ADDR_IPv4, IOS_CELLULAR @"/" IP_ADDR_IPv6 ] :
52 | @[ IOS_VPN @"/" IP_ADDR_IPv6, IOS_VPN @"/" IP_ADDR_IPv4, IOS_WIFI @"/" IP_ADDR_IPv6, IOS_WIFI @"/" IP_ADDR_IPv4, IOS_CELLULAR @"/" IP_ADDR_IPv6, IOS_CELLULAR @"/" IP_ADDR_IPv4 ] ;
53 |
54 | NSDictionary *addresses = [self getIPAddresses];
55 | NSLog(@"addresses: %@", addresses);
56 |
57 | __block NSString *address;
58 | [searchArray enumerateObjectsUsingBlock:^(NSString *key, NSUInteger idx, BOOL *stop) {
59 | address = addresses[key];
60 | //筛选出IP地址格式
61 | if([self isValidatIP:address]) *stop = YES;
62 | } ];
63 | return address ? address : @"0.0.0.0";
64 | }
65 |
66 | + (BOOL)isValidatIP:(NSString *)ipAddress {
67 | if (ipAddress.length == 0) {
68 | return NO;
69 | }
70 | NSString *urlRegEx = @"^([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\."
71 | "([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\."
72 | "([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\."
73 | "([01]?\\d\\d?|2[0-4]\\d|25[0-5])$";
74 |
75 | NSError *error;
76 | NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:urlRegEx options:0 error:&error];
77 |
78 | if (regex != nil) {
79 | NSTextCheckingResult *firstMatch=[regex firstMatchInString:ipAddress options:0 range:NSMakeRange(0, [ipAddress length])];
80 |
81 | if (firstMatch) {
82 | NSRange resultRange = [firstMatch rangeAtIndex:0];
83 | NSString *result=[ipAddress substringWithRange:resultRange];
84 | //输出结果
85 | NSLog(@"ESPTools 输出结果:%@",result);
86 | return YES;
87 | }
88 | }
89 | return NO;
90 | }
91 |
92 | + (NSDictionary *)getIPAddresses {
93 | NSMutableDictionary *addresses = [NSMutableDictionary dictionaryWithCapacity:8];
94 |
95 | // retrieve the current interfaces - returns 0 on success
96 | struct ifaddrs *interfaces;
97 | if(!getifaddrs(&interfaces)) {
98 | // Loop through linked list of interfaces
99 | struct ifaddrs *interface;
100 | for(interface=interfaces; interface; interface=interface->ifa_next) {
101 | if(!(interface->ifa_flags & IFF_UP) /* || (interface->ifa_flags & IFF_LOOPBACK) */ ) {
102 | continue; // deeply nested code harder to read
103 | }
104 | const struct sockaddr_in *addr = (const struct sockaddr_in*)interface->ifa_addr;
105 | char addrBuf[ MAX(INET_ADDRSTRLEN, INET6_ADDRSTRLEN) ];
106 | if(addr && (addr->sin_family==AF_INET || addr->sin_family==AF_INET6)) {
107 | NSString *name = [NSString stringWithUTF8String:interface->ifa_name];
108 | NSString *type;
109 | if(addr->sin_family == AF_INET) {
110 | if(inet_ntop(AF_INET, &addr->sin_addr, addrBuf, INET_ADDRSTRLEN)) {
111 | type = IP_ADDR_IPv4;
112 | }
113 | } else {
114 | const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6*)interface->ifa_addr;
115 | if(inet_ntop(AF_INET6, &addr6->sin6_addr, addrBuf, INET6_ADDRSTRLEN)) {
116 | type = IP_ADDR_IPv6;
117 | }
118 | }
119 | if(type) {
120 | NSString *key = [NSString stringWithFormat:@"%@/%@", name, type];
121 | addresses[key] = [NSString stringWithUTF8String:addrBuf];
122 | }
123 | }
124 | }
125 | // Free memory
126 | freeifaddrs(interfaces);
127 | }
128 | return [addresses count] ? addresses : nil;
129 | }
130 |
131 | @end
132 |
133 |
--------------------------------------------------------------------------------
/android/src/main/java/esptouch/protocol/DatumCode.java:
--------------------------------------------------------------------------------
1 | package esptouch.protocol;
2 |
3 | import java.net.InetAddress;
4 | import java.util.LinkedList;
5 |
6 | import esptouch.task.ICodeData;
7 | import esptouch.util.ByteUtil;
8 | import esptouch.util.CRC8;
9 |
10 | public class DatumCode implements ICodeData {
11 |
12 | // define by the Esptouch protocol, all of the datum code should add 1 at last to prevent 0
13 | private static final int EXTRA_LEN = 40;
14 | private static final int EXTRA_HEAD_LEN = 5;
15 |
16 | private final LinkedList mDataCodes;
17 |
18 | /**
19 | * Constructor of DatumCode
20 | *
21 | * @param apSsid the Ap's ssid
22 | * @param apBssid the Ap's bssid
23 | * @param apPassword the Ap's password
24 | * @param ipAddress the ip address of the phone or pad
25 | * @param isSsidHiden whether the Ap's ssid is hidden
26 | */
27 | public DatumCode(byte[] apSsid, byte[] apBssid, byte[] apPassword,
28 | InetAddress ipAddress, boolean isSsidHiden) {
29 | // Data = total len(1 byte) + apPwd len(1 byte) + SSID CRC(1 byte) +
30 | // BSSID CRC(1 byte) + TOTAL XOR(1 byte)+ ipAddress(4 byte) + apPwd + apSsid apPwdLen <=
31 | // 105 at the moment
32 |
33 | // total xor
34 | char totalXor = 0;
35 |
36 | char apPwdLen = (char) apPassword.length;
37 | CRC8 crc = new CRC8();
38 | crc.update(apSsid);
39 | char apSsidCrc = (char) crc.getValue();
40 |
41 | crc.reset();
42 | crc.update(apBssid);
43 | char apBssidCrc = (char) crc.getValue();
44 |
45 | char apSsidLen = (char) apSsid.length;
46 |
47 | byte[] ipBytes = ipAddress.getAddress();
48 | int ipLen = ipBytes.length;
49 |
50 | char _totalLen = (char) (EXTRA_HEAD_LEN + ipLen + apPwdLen + apSsidLen);
51 | char totalLen = isSsidHiden ? (char) (EXTRA_HEAD_LEN + ipLen + apPwdLen + apSsidLen)
52 | : (char) (EXTRA_HEAD_LEN + ipLen + apPwdLen);
53 |
54 | // build data codes
55 | mDataCodes = new LinkedList<>();
56 | mDataCodes.add(new DataCode(_totalLen, 0));
57 | totalXor ^= _totalLen;
58 | mDataCodes.add(new DataCode(apPwdLen, 1));
59 | totalXor ^= apPwdLen;
60 | mDataCodes.add(new DataCode(apSsidCrc, 2));
61 | totalXor ^= apSsidCrc;
62 | mDataCodes.add(new DataCode(apBssidCrc, 3));
63 | totalXor ^= apBssidCrc;
64 | // ESPDataCode 4 is null
65 | for (int i = 0; i < ipLen; ++i) {
66 | char c = ByteUtil.convertByte2Uint8(ipBytes[i]);
67 | totalXor ^= c;
68 | mDataCodes.add(new DataCode(c, i + EXTRA_HEAD_LEN));
69 | }
70 |
71 | for (int i = 0; i < apPassword.length; i++) {
72 | char c = ByteUtil.convertByte2Uint8(apPassword[i]);
73 | totalXor ^= c;
74 | mDataCodes.add(new DataCode(c, i + EXTRA_HEAD_LEN + ipLen));
75 | }
76 |
77 | // totalXor will xor apSsidChars no matter whether the ssid is hidden
78 | for (int i = 0; i < apSsid.length; i++) {
79 | char c = ByteUtil.convertByte2Uint8(apSsid[i]);
80 | totalXor ^= c;
81 | if (isSsidHiden) {
82 | mDataCodes.add(new DataCode(c, i + EXTRA_HEAD_LEN + ipLen + apPwdLen));
83 | }
84 | }
85 |
86 | // add total xor last
87 | mDataCodes.add(4, new DataCode(totalXor, 4));
88 |
89 | // add bssid
90 | int bssidInsertIndex = EXTRA_HEAD_LEN;
91 | for (int i = 0; i < apBssid.length; i++) {
92 | int index = totalLen + i;
93 | char c = ByteUtil.convertByte2Uint8(apBssid[i]);
94 | DataCode dc = new DataCode(c, index);
95 | if (bssidInsertIndex >= mDataCodes.size()) {
96 | mDataCodes.add(dc);
97 | } else {
98 | mDataCodes.add(bssidInsertIndex, dc);
99 | }
100 | bssidInsertIndex += 4;
101 | }
102 | }
103 |
104 | @Override
105 | public byte[] getBytes() {
106 | byte[] datumCode = new byte[mDataCodes.size() * DataCode.DATA_CODE_LEN];
107 | int index = 0;
108 | for (DataCode dc : mDataCodes) {
109 | for (byte b : dc.getBytes()) {
110 | datumCode[index++] = b;
111 | }
112 | }
113 | return datumCode;
114 | }
115 |
116 | @Override
117 | public String toString() {
118 | StringBuilder sb = new StringBuilder();
119 | byte[] dataBytes = getBytes();
120 | for (byte dataByte : dataBytes) {
121 | String hexString = ByteUtil.convertByte2HexString(dataByte);
122 | sb.append("0x");
123 | if (hexString.length() == 1) {
124 | sb.append("0");
125 | }
126 | sb.append(hexString).append(" ");
127 | }
128 | return sb.toString();
129 | }
130 |
131 | @Override
132 | public char[] getU8s() {
133 | byte[] dataBytes = getBytes();
134 | int len = dataBytes.length / 2;
135 | char[] dataU8s = new char[len];
136 | byte high, low;
137 | for (int i = 0; i < len; i++) {
138 | high = dataBytes[i * 2];
139 | low = dataBytes[i * 2 + 1];
140 | dataU8s[i] = (char) (ByteUtil.combine2bytesToU16(high, low) + EXTRA_LEN);
141 | }
142 | return dataU8s;
143 | }
144 | }
145 |
--------------------------------------------------------------------------------
/android/src/main/java/esptouch/task/EsptouchTaskParameter.java:
--------------------------------------------------------------------------------
1 | package esptouch.task;
2 |
3 | public class EsptouchTaskParameter implements IEsptouchTaskParameter {
4 |
5 | private static int _datagramCount = 0;
6 | private long mIntervalGuideCodeMillisecond;
7 | private long mIntervalDataCodeMillisecond;
8 | private long mTimeoutGuideCodeMillisecond;
9 | private long mTimeoutDataCodeMillisecond;
10 | private int mTotalRepeatTime;
11 | private int mEsptouchResultOneLen;
12 | private int mEsptouchResultMacLen;
13 | private int mEsptouchResultIpLen;
14 | private int mEsptouchResultTotalLen;
15 | private int mPortListening;
16 | private int mTargetPort;
17 | private int mWaitUdpReceivingMilliseond;
18 | private int mWaitUdpSendingMillisecond;
19 | private int mThresholdSucBroadcastCount;
20 | private int mExpectTaskResultCount;
21 | private boolean mBroadcast = true;
22 |
23 | public EsptouchTaskParameter() {
24 | mIntervalGuideCodeMillisecond = 8;
25 | mIntervalDataCodeMillisecond = 8;
26 | mTimeoutGuideCodeMillisecond = 2000;
27 | mTimeoutDataCodeMillisecond = 4000;
28 | mTotalRepeatTime = 1;
29 | mEsptouchResultOneLen = 1;
30 | mEsptouchResultMacLen = 6;
31 | mEsptouchResultIpLen = 4;
32 | mEsptouchResultTotalLen = 1 + 6 + 4;
33 | mPortListening = 18266;
34 | mTargetPort = 7001;
35 | mWaitUdpReceivingMilliseond = 15000;
36 | mWaitUdpSendingMillisecond = 45000;
37 | mThresholdSucBroadcastCount = 1;
38 | mExpectTaskResultCount = 1;
39 | }
40 |
41 | // the range of the result should be 1-100
42 | private static int __getNextDatagramCount() {
43 | return 1 + (_datagramCount++) % 100;
44 | }
45 |
46 | @Override
47 | public long getIntervalGuideCodeMillisecond() {
48 | return mIntervalGuideCodeMillisecond;
49 | }
50 |
51 | @Override
52 | public long getIntervalDataCodeMillisecond() {
53 | return mIntervalDataCodeMillisecond;
54 | }
55 |
56 | @Override
57 | public long getTimeoutGuideCodeMillisecond() {
58 | return mTimeoutGuideCodeMillisecond;
59 | }
60 |
61 | @Override
62 | public long getTimeoutDataCodeMillisecond() {
63 | return mTimeoutDataCodeMillisecond;
64 | }
65 |
66 | @Override
67 | public long getTimeoutTotalCodeMillisecond() {
68 | return mTimeoutGuideCodeMillisecond + mTimeoutDataCodeMillisecond;
69 | }
70 |
71 | @Override
72 | public int getTotalRepeatTime() {
73 | return mTotalRepeatTime;
74 | }
75 |
76 | @Override
77 | public int getEsptouchResultOneLen() {
78 | return mEsptouchResultOneLen;
79 | }
80 |
81 | @Override
82 | public int getEsptouchResultMacLen() {
83 | return mEsptouchResultMacLen;
84 | }
85 |
86 | @Override
87 | public int getEsptouchResultIpLen() {
88 | return mEsptouchResultIpLen;
89 | }
90 |
91 | @Override
92 | public int getEsptouchResultTotalLen() {
93 | return mEsptouchResultTotalLen;
94 | }
95 |
96 | @Override
97 | public int getPortListening() {
98 | return mPortListening;
99 | }
100 |
101 | // target hostname is : 234.1.1.1, 234.2.2.2, 234.3.3.3 to 234.100.100.100
102 | @Override
103 | public String getTargetHostname() {
104 | if (mBroadcast) {
105 | return "255.255.255.255";
106 | } else {
107 | int count = __getNextDatagramCount();
108 | return "234." + count + "." + count + "." + count;
109 | }
110 | }
111 |
112 | @Override
113 | public int getTargetPort() {
114 | return mTargetPort;
115 | }
116 |
117 | @Override
118 | public int getWaitUdpReceivingMillisecond() {
119 | return mWaitUdpReceivingMilliseond;
120 | }
121 |
122 | @Override
123 | public int getWaitUdpSendingMillisecond() {
124 | return mWaitUdpSendingMillisecond;
125 | }
126 |
127 | @Override
128 | public int getWaitUdpTotalMillisecond() {
129 | return mWaitUdpReceivingMilliseond + mWaitUdpSendingMillisecond;
130 | }
131 |
132 | @Override
133 | public void setWaitUdpTotalMillisecond(int waitUdpTotalMillisecond) {
134 | if (waitUdpTotalMillisecond < mWaitUdpReceivingMilliseond
135 | + getTimeoutTotalCodeMillisecond()) {
136 | // if it happen, even one turn about sending udp broadcast can't be
137 | // completed
138 | throw new IllegalArgumentException(
139 | "waitUdpTotalMillisecod is invalid, "
140 | + "it is less than mWaitUdpReceivingMilliseond + getTimeoutTotalCodeMillisecond()");
141 | }
142 | mWaitUdpSendingMillisecond = waitUdpTotalMillisecond
143 | - mWaitUdpReceivingMilliseond;
144 | }
145 |
146 | @Override
147 | public int getThresholdSucBroadcastCount() {
148 | return mThresholdSucBroadcastCount;
149 | }
150 |
151 | @Override
152 | public int getExpectTaskResultCount() {
153 | return this.mExpectTaskResultCount;
154 | }
155 |
156 | @Override
157 | public void setExpectTaskResultCount(int expectTaskResultCount) {
158 | this.mExpectTaskResultCount = expectTaskResultCount;
159 | }
160 |
161 | @Override
162 | public void setBroadcast(boolean broadcast) {
163 | mBroadcast = broadcast;
164 | }
165 | }
166 |
--------------------------------------------------------------------------------
/ios/EspTouch/ESPUtils/ESP_NetUtil.m:
--------------------------------------------------------------------------------
1 | //
2 | // ESPNetUtil.m
3 | // EspTouchDemo
4 | //
5 | // Created by fby on 5/15/15.
6 | // Copyright (c) 2015 fby. All rights reserved.
7 | //
8 |
9 | #import "ESP_NetUtil.h"
10 | #import "ESP_WifiUtil.h"
11 | #import "ESP_ByteUtil.h"
12 | #import "ESPVersionMacro.h"
13 |
14 | #define IP4_LEN 4
15 |
16 | #define IP6_LEN 16
17 |
18 | @implementation ESP_NetUtil
19 |
20 | /**
21 | * get local ip v4 or nil
22 | *
23 | * @return local ip v4 or nil
24 | */
25 | + (NSString *) getLocalIPv4
26 | {
27 | return [ESP_WifiUtil getIPAddress4];
28 | }
29 |
30 | /**
31 | * get local ip v6 or nil
32 | *
33 | * @return local ip v6 or nil
34 | */
35 | + (NSString *) getLocalIPv6
36 | {
37 | return [ESP_WifiUtil getIpAddress6];
38 | }
39 |
40 | + (BOOL) isIPv4Addr:(NSString *)ipAddr
41 | {
42 | NSArray *ip4array = [ipAddr componentsSeparatedByString:@"."];
43 | return [ip4array count]==4;
44 | }
45 |
46 | + (BOOL) isIPv4PrivateAddr:(NSString *)ipAddr4
47 | {
48 | NSArray *ip4array = [ipAddr4 componentsSeparatedByString:@"."];
49 | Byte byte0 = [[ip4array objectAtIndex:0]intValue];
50 | Byte byte1 = [[ip4array objectAtIndex:1]intValue];
51 | // Byte byte2 = [[ip4array objectAtIndex:2]intValue];
52 | // Byte byte3 = [[ip4array objectAtIndex:3]intValue];
53 |
54 | if (byte0==10) {
55 | // 10.0.0.0~10.255.255.255
56 | return YES;
57 | } else if (byte0==172&&16<=byte1&&byte1<=31) {
58 | // 172.16.0.0~172.31.255.255
59 | return YES;
60 | } else if (byte0==192&&byte1==168) {
61 | // 192.168.0.0~192.168.255.255
62 | return YES;
63 | }
64 | return NO;
65 | }
66 |
67 | + (NSData *) getLocalInetAddress4ByAddr:(NSString *) localInetAddr4
68 | {
69 | NSArray *ip4array = [localInetAddr4 componentsSeparatedByString:@"."];
70 | Byte byte0 = [[ip4array objectAtIndex:0]intValue];
71 | Byte byte1 = [[ip4array objectAtIndex:1]intValue];
72 | Byte byte2 = [[ip4array objectAtIndex:2]intValue];
73 | Byte byte3 = [[ip4array objectAtIndex:3]intValue];
74 | Byte bytes[] = {byte0,byte1,byte2,byte3};
75 | NSData *ip4data = [NSData dataWithBytes:bytes length:IP4_LEN];
76 | return ip4data;
77 | }
78 |
79 | + (NSData *) getLocalInetAddress6ByPort:(int) localPort
80 | {
81 | Byte lowPort = localPort & 0xff;
82 | Byte highPort = (localPort>>8) & 0xff;
83 | Byte bytes[] = {highPort,lowPort,0xff,0xff};
84 | NSData *ip6data = [NSData dataWithBytes:bytes length:IP4_LEN];
85 | return ip6data;
86 | }
87 |
88 | + (NSData *) parseInetAddrByData: (NSData *) inetAddrData andOffset: (int) offset andCount: (int) count
89 | {
90 | return [inetAddrData subdataWithRange:NSMakeRange(offset, count)];
91 | }
92 |
93 | + (NSString *) descriptionInetAddr4ByData: (NSData *) inetAddrData
94 | {
95 | // check whether inetAddrData is belong to IPv4
96 | if ([inetAddrData length]!=IP4_LEN) {
97 | return nil;
98 | }
99 | Byte inetAddrBytes[IP4_LEN];
100 | [inetAddrData getBytes:inetAddrBytes length:IP4_LEN];
101 | // hard coding
102 | return [NSString stringWithFormat:@"%d.%d.%d.%d",inetAddrBytes[0],inetAddrBytes[1],inetAddrBytes[2],inetAddrBytes[3]];
103 | }
104 | + (NSString *) descriptionInetAddr6ByData: (NSData *) inetAddrData
105 | {
106 | // check whether inetAddrData is belong to IPv4
107 | if ([inetAddrData length]!=IP6_LEN) {
108 | return nil;
109 | }
110 | Byte inetAddrBytes[IP6_LEN];
111 | [inetAddrData getBytes:inetAddrBytes length:IP6_LEN];
112 | // hard coding
113 | return [NSString stringWithFormat:@"%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x",inetAddrBytes[0],inetAddrBytes[1],inetAddrBytes[2],inetAddrBytes[3],inetAddrBytes[4],inetAddrBytes[5],inetAddrBytes[6],inetAddrBytes[7],inetAddrBytes[8],inetAddrBytes[9],inetAddrBytes[10],inetAddrBytes[11],inetAddrBytes[12],inetAddrBytes[13],inetAddrBytes[14],inetAddrBytes[15]];
114 | }
115 |
116 | + (NSData *) parseBssid2bytes: (NSString *) bssid
117 | {
118 | NSArray *bssidArray = [bssid componentsSeparatedByString:@":"];
119 | NSInteger size = [bssidArray count];
120 | Byte bssidBytes[size];
121 | for (NSInteger i = 0; i < size; i++) {
122 | NSString *bssidStr = [bssidArray objectAtIndex:i];
123 | bssidBytes[i] = strtoul([bssidStr UTF8String], 0, 16);
124 | }
125 | return [[NSData alloc]initWithBytes:bssidBytes length:size];
126 | }
127 |
128 | + (NSURLSessionConfiguration *) DEFAULT_SESSION_CONFIGURATION
129 | {
130 | static dispatch_once_t predicate;
131 | static NSURLSessionConfiguration *DEFAULT_SESSION_CONFIGURATION;
132 | dispatch_once(&predicate, ^{
133 | DEFAULT_SESSION_CONFIGURATION = [NSURLSessionConfiguration defaultSessionConfiguration];
134 | });
135 | return DEFAULT_SESSION_CONFIGURATION;
136 | }
137 |
138 |
139 | + (void) tryOpenNetworkPermission
140 | {
141 | // only ios 10.0 later required to try open network permission
142 | if(SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"10.0")) {
143 | NSURL *url = [NSURL URLWithString:@"https://8.8.8.8"];
144 | NSURLRequest *request = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:1000];
145 |
146 |
147 | NSURLSession *urlSession = [NSURLSession sessionWithConfiguration:[self DEFAULT_SESSION_CONFIGURATION] delegate:nil delegateQueue:[NSOperationQueue currentQueue]];
148 | [[urlSession dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error){
149 | }] resume];
150 | }
151 | }
152 |
153 | @end
154 |
--------------------------------------------------------------------------------
/android/src/main/java/com/reactnativesmartconfigswjava/SmartconfigSwjavaModule.java:
--------------------------------------------------------------------------------
1 |
2 | package com.reactnativesmartconfigswjava;
3 |
4 | import android.os.AsyncTask;
5 | import android.os.Handler;
6 | import android.os.Looper;
7 | import android.os.Message;
8 | import android.util.Log;
9 |
10 | import com.facebook.react.bridge.Arguments;
11 | import com.facebook.react.bridge.Promise;
12 | import com.facebook.react.bridge.ReactApplicationContext;
13 | import com.facebook.react.bridge.ReactContextBaseJavaModule;
14 | import com.facebook.react.bridge.ReactMethod;
15 | import com.facebook.react.bridge.WritableMap;
16 | import com.facebook.react.modules.core.DeviceEventManagerModule;
17 |
18 | import org.json.JSONException;
19 | import org.json.JSONObject;
20 |
21 | import java.util.List;
22 |
23 | import esptouch.EsptouchTask;
24 | import esptouch.IEsptouchListener;
25 | import esptouch.IEsptouchResult;
26 | import esptouch.IEsptouchTask;
27 |
28 |
29 | public class SmartconfigSwjavaModule extends ReactContextBaseJavaModule {
30 |
31 | private static final String TAG = "SmartconfigSwjavaModule";
32 |
33 | private final ReactApplicationContext _reactContext;
34 |
35 | private IEsptouchTask mEsptouchTask;
36 |
37 | public SmartconfigSwjavaModule(ReactApplicationContext reactContext) {
38 | super(reactContext);
39 | _reactContext = reactContext;
40 |
41 | }
42 |
43 | @Override
44 | public String getName() {
45 | return "SmartconfigSwjava";
46 | }
47 |
48 | @ReactMethod
49 | public void stop() {
50 | if (mEsptouchTask != null) {
51 | Log.d(TAG, "cancel task");
52 | mEsptouchTask.interrupt();
53 | }
54 | }
55 |
56 | @ReactMethod
57 | public void start(String ssid, String bssid, String pass, int timeout, int taskCount, final Promise promise) {
58 | Log.d(TAG, "ssid " + ssid + ":pass " + pass);
59 | stop();
60 | new EsptouchAsyncTask(result -> onFinishScan())
61 | .execute(ssid, bssid, pass, Integer.toString(taskCount), Integer.toString(timeout));
62 | }
63 |
64 |
65 | public interface TaskListener {
66 | public void onFinished(List result);
67 | }
68 |
69 | private void sendToRN(String eventName, String data) {
70 | String eventSendToRN = "SmartConfig";
71 | Log.d(TAG, "send to RN " + eventName + " " + data);
72 | // Create map for params
73 | WritableMap payload = Arguments.createMap();
74 | // Put data to map
75 | payload.putString("eventName", eventName);
76 | payload.putString("data", data);
77 | // Get EventEmitter from context and send event thanks to it
78 | _reactContext
79 | .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
80 | .emit(eventSendToRN, payload);
81 | }
82 |
83 | private Handler handler = new Handler(Looper.getMainLooper()) {
84 | @Override
85 | public void handleMessage(Message message) {
86 | String data = (String) message.obj;
87 | sendToRN("onFoundDevice", data);
88 | }
89 | };
90 |
91 | private void onFoundDevice(String data) {
92 | Message message = handler.obtainMessage(0, data);
93 | message.sendToTarget();
94 | }
95 |
96 | private void onFinishScan() {
97 | sendToRN("onFinishScan", "");
98 | }
99 |
100 | private class EsptouchAsyncTask extends AsyncTask> {
101 | private final TaskListener taskListener;
102 |
103 | public EsptouchAsyncTask(TaskListener listener) {
104 | // The listener reference is passed in through the constructor
105 | this.taskListener = listener;
106 | }
107 |
108 |
109 | // without the lock, if the user tap confirm and cancel quickly enough,
110 | // the bug will arise. the reason is follows:
111 | // 0. task is starting created, but not finished
112 | // 1. the task is cancel for the task hasn't been created, it do nothing
113 | // 2. task is created
114 | // 3. Oops, the task should be cancelled, but it is running
115 | private final Object mLock = new Object();
116 |
117 | @Override
118 | protected void onPreExecute() {
119 | Log.d(TAG, "Begin task");
120 | }
121 |
122 | @Override
123 | protected List doInBackground(String... params) {
124 | Log.d(TAG, "doing task");
125 | int taskCount = -1;
126 | int timeout = 60000;
127 | synchronized (mLock) {
128 | String apSsid = params[0];
129 | String apBssid = params[1];
130 | String apPassword = params[2];
131 | Log.d(TAG, apSsid + " | " + apBssid + " | " + apPassword);
132 | String taskCountStr = params[3];
133 | String timeoutStr = params[4];
134 | taskCount = Integer.parseInt(taskCountStr);
135 | timeout = Integer.parseInt(timeoutStr);
136 | mEsptouchTask = new EsptouchTask(apSsid, apBssid, apPassword, _reactContext);
137 | mEsptouchTask.setPackageBroadcast(false);
138 | mEsptouchTask.setEsptouchListener(result -> {
139 | String ip = result.getInetAddress().getHostAddress();
140 | String bssid = result.getBssid();
141 | String data = "{\"ip\":\"" + ip + "\", \"bssid\":\"" + bssid + "\"}";
142 | onFoundDevice(data);
143 | });
144 | }
145 | List resultList = mEsptouchTask.executeForResults(taskCount);
146 | return resultList;
147 | }
148 |
149 | @Override
150 | protected void onPostExecute(List result) {
151 |
152 | IEsptouchResult firstResult = result.get(0);
153 | // check whether the task is cancelled and no results received
154 | if (!firstResult.isCancelled()) {
155 | if (this.taskListener != null) {
156 |
157 | // And if it is we call the callback function on it.
158 | this.taskListener.onFinished(result);
159 | }
160 | }
161 | }
162 | }
163 | }
164 |
--------------------------------------------------------------------------------
/android/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | #
4 | # Copyright 2015 the original author or authors.
5 | #
6 | # Licensed under the Apache License, Version 2.0 (the "License");
7 | # you may not use this file except in compliance with the License.
8 | # You may obtain a copy of the License at
9 | #
10 | # https://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | # See the License for the specific language governing permissions and
16 | # limitations under the License.
17 | #
18 |
19 | ##############################################################################
20 | ##
21 | ## Gradle start up script for UN*X
22 | ##
23 | ##############################################################################
24 |
25 | # Attempt to set APP_HOME
26 | # Resolve links: $0 may be a link
27 | PRG="$0"
28 | # Need this for relative symlinks.
29 | while [ -h "$PRG" ] ; do
30 | ls=`ls -ld "$PRG"`
31 | link=`expr "$ls" : '.*-> \(.*\)$'`
32 | if expr "$link" : '/.*' > /dev/null; then
33 | PRG="$link"
34 | else
35 | PRG=`dirname "$PRG"`"/$link"
36 | fi
37 | done
38 | SAVED="`pwd`"
39 | cd "`dirname \"$PRG\"`/" >/dev/null
40 | APP_HOME="`pwd -P`"
41 | cd "$SAVED" >/dev/null
42 |
43 | APP_NAME="Gradle"
44 | APP_BASE_NAME=`basename "$0"`
45 |
46 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
47 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
48 |
49 | # Use the maximum available, or set MAX_FD != -1 to use that value.
50 | MAX_FD="maximum"
51 |
52 | warn () {
53 | echo "$*"
54 | }
55 |
56 | die () {
57 | echo
58 | echo "$*"
59 | echo
60 | exit 1
61 | }
62 |
63 | # OS specific support (must be 'true' or 'false').
64 | cygwin=false
65 | msys=false
66 | darwin=false
67 | nonstop=false
68 | case "`uname`" in
69 | CYGWIN* )
70 | cygwin=true
71 | ;;
72 | Darwin* )
73 | darwin=true
74 | ;;
75 | MINGW* )
76 | msys=true
77 | ;;
78 | NONSTOP* )
79 | nonstop=true
80 | ;;
81 | esac
82 |
83 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
84 |
85 | # Determine the Java command to use to start the JVM.
86 | if [ -n "$JAVA_HOME" ] ; then
87 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
88 | # IBM's JDK on AIX uses strange locations for the executables
89 | JAVACMD="$JAVA_HOME/jre/sh/java"
90 | else
91 | JAVACMD="$JAVA_HOME/bin/java"
92 | fi
93 | if [ ! -x "$JAVACMD" ] ; then
94 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
95 |
96 | Please set the JAVA_HOME variable in your environment to match the
97 | location of your Java installation."
98 | fi
99 | else
100 | JAVACMD="java"
101 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
102 |
103 | Please set the JAVA_HOME variable in your environment to match the
104 | location of your Java installation."
105 | fi
106 |
107 | # Increase the maximum file descriptors if we can.
108 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
109 | MAX_FD_LIMIT=`ulimit -H -n`
110 | if [ $? -eq 0 ] ; then
111 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
112 | MAX_FD="$MAX_FD_LIMIT"
113 | fi
114 | ulimit -n $MAX_FD
115 | if [ $? -ne 0 ] ; then
116 | warn "Could not set maximum file descriptor limit: $MAX_FD"
117 | fi
118 | else
119 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
120 | fi
121 | fi
122 |
123 | # For Darwin, add options to specify how the application appears in the dock
124 | if $darwin; then
125 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
126 | fi
127 |
128 | # For Cygwin or MSYS, switch paths to Windows format before running java
129 | if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
130 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
131 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
132 | JAVACMD=`cygpath --unix "$JAVACMD"`
133 |
134 | # We build the pattern for arguments to be converted via cygpath
135 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
136 | SEP=""
137 | for dir in $ROOTDIRSRAW ; do
138 | ROOTDIRS="$ROOTDIRS$SEP$dir"
139 | SEP="|"
140 | done
141 | OURCYGPATTERN="(^($ROOTDIRS))"
142 | # Add a user-defined pattern to the cygpath arguments
143 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
144 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
145 | fi
146 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
147 | i=0
148 | for arg in "$@" ; do
149 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
150 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
151 |
152 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
153 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
154 | else
155 | eval `echo args$i`="\"$arg\""
156 | fi
157 | i=`expr $i + 1`
158 | done
159 | case $i in
160 | 0) set -- ;;
161 | 1) set -- "$args0" ;;
162 | 2) set -- "$args0" "$args1" ;;
163 | 3) set -- "$args0" "$args1" "$args2" ;;
164 | 4) set -- "$args0" "$args1" "$args2" "$args3" ;;
165 | 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
166 | 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
167 | 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
168 | 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
169 | 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
170 | esac
171 | fi
172 |
173 | # Escape application args
174 | save () {
175 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
176 | echo " "
177 | }
178 | APP_ARGS=`save "$@"`
179 |
180 | # Collect all arguments for the java command, following the shell quoting and substitution rules
181 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
182 |
183 | exec "$JAVACMD" "$@"
184 |
--------------------------------------------------------------------------------
/ios/EspTouch/protocol/ESPDatumCode.m:
--------------------------------------------------------------------------------
1 | //
2 | // ESPDatumCode.m
3 | // EspTouchDemo
4 | //
5 | // Created by fby on 4/9/15.
6 | // Copyright (c) 2015 fby. All rights reserved.
7 | //
8 |
9 | #import "ESPDatumCode.h"
10 | #import "ESPDataCode.h"
11 | #import "ESP_ByteUtil.h"
12 | #import "ESP_CRC8.h"
13 | #import "ESP_NetUtil.h"
14 |
15 | // define by the Esptouch protocol, all of the datum code should add EXTRA_LEN to prevent 0
16 | #define EXTRA_LEN 40
17 | #define EXTRA_HEAD_LEN 5
18 |
19 | @implementation ESPDatumCode
20 |
21 | - (id) initWithSsid: (NSData *) apSsid andApBssid: (NSData *) apBssid andApPwd: (NSData*) apPwd andInetAddrData: (NSData *) ipAddrData andIsSsidHidden: (BOOL) isSsidHidden
22 | {
23 | self = [super init];
24 | if (self)
25 | {
26 | // Data = total len(1 byte) + apPwd len(1 byte) + SSID CRC(1 byte) +
27 | // BSSID CRC(1 byte) + TOTAL XOR(1 byte) + ipAddress(4 byte) + apPwd + apSsid apPwdLen <=
28 | // 105 at the moment
29 |
30 | // total xor
31 | UInt8 totalXor = 0;
32 |
33 | NSData *apPwdBytesData = apPwd;
34 | NSData *apSsidBytesData = apSsid;
35 | Byte apPwdBytes[[apPwdBytesData length]];
36 | Byte apSsidBytes[[apSsidBytesData length]];
37 | [apPwdBytesData getBytes:apPwdBytes length:[apPwdBytesData length]];
38 | [apSsidBytesData getBytes:apSsidBytes length:[apSsidBytesData length]];
39 | Byte apPwdLen = [apPwdBytesData length];
40 | ESP_CRC8 *crc = [[ESP_CRC8 alloc]init];
41 | [crc updateWithBuf:apSsidBytes Nbytes:(int)sizeof(apSsidBytes)];
42 | Byte apSsidCrc = [crc getValue];
43 |
44 | [crc reset];
45 | NSData *apBssidData = apBssid;
46 | int apBssidDataLen = (int)[apBssidData length];
47 | Byte apBssidBytes[apBssidDataLen];
48 | [apBssidData getBytes:apBssidBytes length:[apBssidData length]];
49 | [crc updateWithBuf:apBssidBytes Nbytes:apBssidDataLen];
50 | UInt8 apBssidCrc = [crc getValue];
51 |
52 | UInt8 apSsidLen = sizeof(apSsidBytes);
53 |
54 | // only support ipv4 at the moment
55 | UInt8 ipLen = [ipAddrData length];
56 | Byte ipAddrUint8s[ipLen];
57 | [ipAddrData getBytes:ipAddrUint8s length:[ipAddrData length]];
58 |
59 | UInt8 _totalLen = EXTRA_HEAD_LEN + ipLen + apPwdLen + apSsidLen;
60 | UInt8 totalLen = isSsidHidden ? (EXTRA_HEAD_LEN + ipLen + apPwdLen + apSsidLen):(EXTRA_HEAD_LEN + ipLen + apPwdLen);
61 |
62 | // build data codes
63 | _dataCodes = [[NSMutableArray alloc]initWithCapacity:totalLen + apBssidDataLen];
64 |
65 | ESPDataCode *dataCode = [[ESPDataCode alloc]initWithU8:_totalLen andIndex:0];
66 | [_dataCodes addObject:dataCode];
67 | totalXor ^= _totalLen;
68 | dataCode = [[ESPDataCode alloc]initWithU8:apPwdLen andIndex:1];
69 | [_dataCodes addObject:dataCode];
70 | totalXor ^= apPwdLen;
71 | dataCode = [[ESPDataCode alloc]initWithU8:apSsidCrc andIndex:2];
72 | [_dataCodes addObject:dataCode];
73 | totalXor ^= apSsidCrc;
74 | dataCode = [[ESPDataCode alloc]initWithU8:apBssidCrc andIndex:3];
75 | [_dataCodes addObject:dataCode];
76 | totalXor ^= apBssidCrc;
77 | // ESPDataCode 4 is nil
78 | for (int i = 0; i < ipLen; i++)
79 | {
80 | dataCode = [[ESPDataCode alloc]initWithU8:ipAddrUint8s[i] andIndex:i + EXTRA_HEAD_LEN];
81 | [_dataCodes addObject:dataCode];
82 | totalXor ^= ipAddrUint8s[i];
83 | }
84 | for (int i = 0; i < apPwdLen; i++)
85 | {
86 | dataCode = [[ESPDataCode alloc]initWithU8:apPwdBytes[i] andIndex:i + EXTRA_HEAD_LEN + ipLen];
87 | [_dataCodes addObject:dataCode];
88 | totalXor ^= apPwdBytes[i];
89 | }
90 |
91 | // totalXor will xor apSsidChars no matter whether the ssid is hidden
92 | for (int i = 0; i < apSsidLen; i++)
93 | {
94 | totalXor ^= apSsidBytes[i];
95 | }
96 |
97 | if (isSsidHidden)
98 | {
99 | for (int i = 0; i < apSsidLen; i++)
100 | {
101 | dataCode = [[ESPDataCode alloc]initWithU8:apSsidBytes[i] andIndex:i + EXTRA_HEAD_LEN + ipLen + apPwdLen];
102 | [_dataCodes addObject:dataCode];
103 | }
104 | }
105 |
106 | // add total xor last
107 | dataCode = [[ESPDataCode alloc]initWithU8:totalXor andIndex:4];
108 | [_dataCodes insertObject:dataCode atIndex:4];
109 |
110 | // add bssid
111 | NSUInteger bssidInsertIndex = EXTRA_HEAD_LEN;
112 | for (int i = 0; i < apBssidDataLen; i++) {
113 | int index = totalLen + i;
114 | Byte b = apBssidBytes[i];
115 | ESPDataCode *dc = [[ESPDataCode alloc] initWithU8:b andIndex:index];
116 | if (bssidInsertIndex >= _dataCodes.count) {
117 | [_dataCodes addObject:dc];
118 | } else {
119 | [_dataCodes insertObject:dc atIndex:bssidInsertIndex];
120 | }
121 | bssidInsertIndex += 4;
122 | }
123 | }
124 | return self;
125 | }
126 |
127 | - (NSData *) getBytes
128 | {
129 | Byte datumCode[[_dataCodes count] * DATA_CODE_LEN];
130 | for (int i = 0; i < [_dataCodes count]; i++)
131 | {
132 | ESPDataCode *dataCode = [_dataCodes objectAtIndex:i];
133 | NSData *bytesData = [dataCode getBytes];
134 | Byte bytes[DATA_CODE_LEN];
135 | [bytesData getBytes:bytes length:DATA_CODE_LEN];
136 | void *dest = datumCode + i * DATA_CODE_LEN * sizeof(Byte);
137 | void *src = bytes;
138 | memcpy(dest, src, DATA_CODE_LEN);
139 | }
140 | return [[NSData alloc]initWithBytes:datumCode length:sizeof(datumCode)];
141 | }
142 |
143 | - (NSData *) getU16s
144 | {
145 | NSData *dataBytes = [self getBytes];
146 | NSInteger totalLen = [dataBytes length];
147 | Byte bytes[totalLen];
148 | [dataBytes getBytes:bytes length:totalLen];
149 | NSInteger len = totalLen / 2;
150 | UInt16 dataU16s[len];
151 | Byte high, low;
152 | for (int i = 0; i < len; i++)
153 | {
154 | high = bytes[i * 2];
155 | low = bytes[i * 2 + 1];
156 | dataU16s[i] = [ESP_ByteUtil combine2bytesToU16WithHigh:high andLow:low] + EXTRA_LEN;
157 | }
158 | return [[NSData alloc]initWithBytes:dataU16s length:totalLen];
159 | }
160 |
161 | - (NSString *)description
162 | {
163 | NSData* data = [self getBytes];
164 | return [ESP_ByteUtil getHexStringByData:data];
165 | }
166 |
167 |
168 | @end
169 |
--------------------------------------------------------------------------------
/example/android/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | #
4 | # Copyright 2015 the original author or authors.
5 | #
6 | # Licensed under the Apache License, Version 2.0 (the "License");
7 | # you may not use this file except in compliance with the License.
8 | # You may obtain a copy of the License at
9 | #
10 | # http://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | # See the License for the specific language governing permissions and
16 | # limitations under the License.
17 | #
18 |
19 | ##############################################################################
20 | ##
21 | ## Gradle start up script for UN*X
22 | ##
23 | ##############################################################################
24 |
25 | # Attempt to set APP_HOME
26 | # Resolve links: $0 may be a link
27 | PRG="$0"
28 | # Need this for relative symlinks.
29 | while [ -h "$PRG" ] ; do
30 | ls=`ls -ld "$PRG"`
31 | link=`expr "$ls" : '.*-> \(.*\)$'`
32 | if expr "$link" : '/.*' > /dev/null; then
33 | PRG="$link"
34 | else
35 | PRG=`dirname "$PRG"`"/$link"
36 | fi
37 | done
38 | SAVED="`pwd`"
39 | cd "`dirname \"$PRG\"`/" >/dev/null
40 | APP_HOME="`pwd -P`"
41 | cd "$SAVED" >/dev/null
42 |
43 | APP_NAME="Gradle"
44 | APP_BASE_NAME=`basename "$0"`
45 |
46 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
47 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
48 |
49 | # Use the maximum available, or set MAX_FD != -1 to use that value.
50 | MAX_FD="maximum"
51 |
52 | warn () {
53 | echo "$*"
54 | }
55 |
56 | die () {
57 | echo
58 | echo "$*"
59 | echo
60 | exit 1
61 | }
62 |
63 | # OS specific support (must be 'true' or 'false').
64 | cygwin=false
65 | msys=false
66 | darwin=false
67 | nonstop=false
68 | case "`uname`" in
69 | CYGWIN* )
70 | cygwin=true
71 | ;;
72 | Darwin* )
73 | darwin=true
74 | ;;
75 | MINGW* )
76 | msys=true
77 | ;;
78 | NONSTOP* )
79 | nonstop=true
80 | ;;
81 | esac
82 |
83 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
84 |
85 | # Determine the Java command to use to start the JVM.
86 | if [ -n "$JAVA_HOME" ] ; then
87 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
88 | # IBM's JDK on AIX uses strange locations for the executables
89 | JAVACMD="$JAVA_HOME/jre/sh/java"
90 | else
91 | JAVACMD="$JAVA_HOME/bin/java"
92 | fi
93 | if [ ! -x "$JAVACMD" ] ; then
94 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
95 |
96 | Please set the JAVA_HOME variable in your environment to match the
97 | location of your Java installation."
98 | fi
99 | else
100 | JAVACMD="java"
101 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
102 |
103 | Please set the JAVA_HOME variable in your environment to match the
104 | location of your Java installation."
105 | fi
106 |
107 | # Increase the maximum file descriptors if we can.
108 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
109 | MAX_FD_LIMIT=`ulimit -H -n`
110 | if [ $? -eq 0 ] ; then
111 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
112 | MAX_FD="$MAX_FD_LIMIT"
113 | fi
114 | ulimit -n $MAX_FD
115 | if [ $? -ne 0 ] ; then
116 | warn "Could not set maximum file descriptor limit: $MAX_FD"
117 | fi
118 | else
119 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
120 | fi
121 | fi
122 |
123 | # For Darwin, add options to specify how the application appears in the dock
124 | if $darwin; then
125 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
126 | fi
127 |
128 | # For Cygwin, switch paths to Windows format before running java
129 | if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
130 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
131 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
132 | JAVACMD=`cygpath --unix "$JAVACMD"`
133 |
134 | # We build the pattern for arguments to be converted via cygpath
135 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
136 | SEP=""
137 | for dir in $ROOTDIRSRAW ; do
138 | ROOTDIRS="$ROOTDIRS$SEP$dir"
139 | SEP="|"
140 | done
141 | OURCYGPATTERN="(^($ROOTDIRS))"
142 | # Add a user-defined pattern to the cygpath arguments
143 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
144 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
145 | fi
146 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
147 | i=0
148 | for arg in "$@" ; do
149 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
150 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
151 |
152 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
153 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
154 | else
155 | eval `echo args$i`="\"$arg\""
156 | fi
157 | i=$((i+1))
158 | done
159 | case $i in
160 | (0) set -- ;;
161 | (1) set -- "$args0" ;;
162 | (2) set -- "$args0" "$args1" ;;
163 | (3) set -- "$args0" "$args1" "$args2" ;;
164 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
165 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
166 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
167 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
168 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
169 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
170 | esac
171 | fi
172 |
173 | # Escape application args
174 | save () {
175 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
176 | echo " "
177 | }
178 | APP_ARGS=$(save "$@")
179 |
180 | # Collect all arguments for the java command, following the shell quoting and substitution rules
181 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
182 |
183 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
184 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
185 | cd "$(dirname "$0")"
186 | fi
187 |
188 | exec "$JAVACMD" "$@"
189 |
--------------------------------------------------------------------------------