From 82699c984d3220e18edf17bd9792b750609bd61f Mon Sep 17 00:00:00 2001 From: Jihun Ha Date: Thu, 4 Jun 2015 14:30:05 +0900 Subject: [PATCH] Add an initial prototype of Multi-Phy Easy Setup service for Arduino device It provides the service library and an sample application using the library. Arduino Mega board and WiFi shield are used for functionlity test. Change-Id: Iadb19361db8a777b84437ad978887dedeb2e6e63 Signed-off-by: Jihun Ha Reviewed-on: https://gerrit.iotivity.org/gerrit/1189 Reviewed-by: Madan Lanka Tested-by: Madan Lanka --- resource/csdk/connectivity/SConscript | 6 +- service/SConscript | 6 +- service/easy-setup/SConscript | 80 ++++ service/easy-setup/sampleapp/SConscript | 43 +++ .../sampleapp/arduino/thinserver/SConscript | 54 +++ .../sampleapp/arduino/thinserver/thinserver.cpp | 116 ++++++ .../sdk/arduino/wifi/inc/networkHandler.h | 76 ++++ .../sdk/arduino/wifi/src/networkHandler.cpp | 185 ++++++++++ service/easy-setup/sdk/inc/common.h | 38 ++ service/easy-setup/sdk/inc/easysetup.h | 56 +++ service/easy-setup/sdk/inc/resourceHandler.h | 78 ++++ service/easy-setup/sdk/src/easysetup.cpp | 129 +++++++ service/easy-setup/sdk/src/resourceHandler.cpp | 404 +++++++++++++++++++++ 13 files changed, 1266 insertions(+), 5 deletions(-) create mode 100644 service/easy-setup/SConscript create mode 100644 service/easy-setup/sampleapp/SConscript create mode 100644 service/easy-setup/sampleapp/arduino/thinserver/SConscript create mode 100755 service/easy-setup/sampleapp/arduino/thinserver/thinserver.cpp create mode 100755 service/easy-setup/sdk/arduino/wifi/inc/networkHandler.h create mode 100755 service/easy-setup/sdk/arduino/wifi/src/networkHandler.cpp create mode 100755 service/easy-setup/sdk/inc/common.h create mode 100755 service/easy-setup/sdk/inc/easysetup.h create mode 100755 service/easy-setup/sdk/inc/resourceHandler.h create mode 100755 service/easy-setup/sdk/src/easysetup.cpp create mode 100755 service/easy-setup/sdk/src/resourceHandler.cpp diff --git a/resource/csdk/connectivity/SConscript b/resource/csdk/connectivity/SConscript index bec1000..3d50078 100644 --- a/resource/csdk/connectivity/SConscript +++ b/resource/csdk/connectivity/SConscript @@ -59,7 +59,7 @@ else: env.SConscript('./src/SConscript') -if build_sample == 'ON': - if target_os in ['linux', 'arduino', 'android']: - env.SConscript('./samples/' + target_os + '/SConscript') +#if build_sample == 'ON': +# if target_os in ['linux', 'arduino', 'android']: +# env.SConscript('./samples/' + target_os + '/SConscript') diff --git a/service/SConscript b/service/SConscript index a3bd70e..92d7f0e 100644 --- a/service/SConscript +++ b/service/SConscript @@ -26,7 +26,7 @@ Import('env') target_os = env.get('TARGET_OS') -if target_os not in ['arduino','darwin','ios']: +if target_os not in ['arduino','darwin']: # Build things manager project SConscript('things-manager/SConscript') @@ -35,7 +35,7 @@ if target_os not in ['arduino','darwin','ios']: # Build protocol plugin project # protocol-plugin use 'inotify', this feature isn't support by MAC OSX - if target_os not in ['darwin', 'ios']: + if target_os not in ['darwin', 'ios', 'android']: SConscript('protocol-plugin/SConscript') # Build notification manager project @@ -43,3 +43,5 @@ if target_os not in ['arduino','darwin','ios']: #else: # SConscript('notification-manager/SampleApp/arduino/SConscript') +if target_os == 'arduino': + SConscript('easy-setup/SConscript') \ No newline at end of file diff --git a/service/easy-setup/SConscript b/service/easy-setup/SConscript new file mode 100644 index 0000000..945b93c --- /dev/null +++ b/service/easy-setup/SConscript @@ -0,0 +1,80 @@ +#****************************************************************** +# +# Copyright 2014 Samsung Electronics All Rights Reserved. +# +#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +## +# easy-setup project build script +## +import os +Import('env') + +# Add third party libraries +lib_env = env.Clone() +#SConscript(env.get('SRC_DIR') + '/service/third_party_libs.scons', exports = 'lib_env') + +easy_setup_env = lib_env.Clone() +target_os = env.get('TARGET_OS') +###################################################################### +# Build flags +###################################################################### +easy_setup_env.AppendUnique(CPPPATH = ['sdk/inc', 'sdk/src']) + +if target_os not in ['windows', 'winrt']: + easy_setup_env.AppendUnique(CXXFLAGS = ['-std=c++0x', '-Wall']) + if target_os not in ['android', 'arduino']: + easy_setup_env.AppendUnique(CXXFLAGS = ['-pthread']) + +if target_os == 'android': + easy_setup_env.AppendUnique(CXXFLAGS = ['-frtti', '-fexceptions']) + easy_setup_env.PrependUnique(LIBS = ['oc', 'octbstack', 'gnustl_shared']) + +if target_os == 'arduino': + easy_setup_env.AppendUnique(CPPPATH = [ + '../../resource/oc_logger/include', + '../../resource/csdk/logger/include', + '../../resource/csdk/stack/include', + '../../extlibs/cjson', + 'sdk/arduino/wifi/inc', + 'sdk/arduino/wifi/src' ]) + +###################################################################### +# Source files and Targets +###################################################################### + +#if target_os == 'arduino': + es_src = env.Glob('sdk/src/*.cpp') + es_src += env.Glob('sdk/arduino/wifi/src/*.cpp') + es_sdk_static = easy_setup_env.StaticLibrary('ESSDKLibrary', es_src) + easy_setup_env.InstallTarget(es_sdk_static, 'libESSDK') + +if target_os == 'android': + es_src = env.Glob('sdk/src/*.cpp') + es_src += env.Glob('sdk/android/wifi/src/*.cpp') + es_sdk_static = easy_setup_env.StaticLibrary('ESLib', es_src) + es_sdk_shared = easy_setup_env.SharedLibrary('ESLib', es_src) + easy_setup_env.InstallTarget([es_sdk_static, es_sdk_shared], 'libESSDK') + +# Build JNI layer +#if target_os == 'android': +# SConscript(os.path.join('sdk', 'java', 'jni', 'SConscript')) + +#Go to build sample apps +SConscript('sampleapp/SConscript') + + diff --git a/service/easy-setup/sampleapp/SConscript b/service/easy-setup/sampleapp/SConscript new file mode 100644 index 0000000..a00282c --- /dev/null +++ b/service/easy-setup/sampleapp/SConscript @@ -0,0 +1,43 @@ +#****************************************************************** +# +# Copyright 2014 Samsung Electronics All Rights Reserved. +# +#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +## +# sampleapp build script +## + +Import('env') + +# Add third party libraries +lib_env = env.Clone() +#SConscript(env.get('SRC_DIR') + '/service/third_party_libs.scons', 'lib_env') +sample_env = lib_env.Clone() +target_os = env.get('TARGET_OS') + +###################################################################### +# Build flags +###################################################################### + +###################################################################### +# Source files and Targets +###################################################################### +if target_os == 'arduino' : + # Build linux sample app + SConscript('arduino/thinserver/SConscript') + diff --git a/service/easy-setup/sampleapp/arduino/thinserver/SConscript b/service/easy-setup/sampleapp/arduino/thinserver/SConscript new file mode 100644 index 0000000..d03e18e --- /dev/null +++ b/service/easy-setup/sampleapp/arduino/thinserver/SConscript @@ -0,0 +1,54 @@ +#****************************************************************** +# +# Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved. +# +#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +Import('env') + +thinserver_env = env.Clone() +###################################################################### +# Build flags +###################################################################### +thinserver_env.PrependUnique(CPPPATH = [ + '../../../../../resource/oc_logger/include', + '../../../../../resource/csdk/logger/include', + '../../../../../resource/csdk/stack/include', + '../../../../../extlibs/cjson', + '../../../sdk/inc', + '../../../sdk/arduino/wifi/inc' + ]) + +thinserver_env.AppendUnique(LIBPATH = [env.get('BUILD_DIR')]) +thinserver_env.AppendUnique(CPPDEFINES = ['TB_LOG', 'ARDUINOWIFI']) + +thinserver_env.PrependUnique(LIBS = ['octbstack', 'connectivity_abstraction','coap', 'ESSDKLibrary']) + +thinserver = thinserver_env.Program('thinserver', 'thinserver.cpp') +env.CreateBin('thinserver') + +i_thinserver = thinserver_env.Install(env.get('BUILD_DIR'), thinserver) + +Alias('thinserver', i_thinserver) +env.AppendTarget('thinserver') + +if(thinserver_env['UPLOAD'] == True): + from sys import platform as _platform + if _platform == "linux" or _platform == "linux2": + thinserver_env.Upload(env.get('BUILD_DIR') + '/service/easy-setup/sampleapp/arduino/thinserver/thinserver.hex') + else: + print 'Please use appropriate install method for your developing machine. Linux is the only supported platform right now.' diff --git a/service/easy-setup/sampleapp/arduino/thinserver/thinserver.cpp b/service/easy-setup/sampleapp/arduino/thinserver/thinserver.cpp new file mode 100755 index 0000000..d352e1e --- /dev/null +++ b/service/easy-setup/sampleapp/arduino/thinserver/thinserver.cpp @@ -0,0 +1,116 @@ +//****************************************************************** +// +// Copyright 2014 Samsung Electronics All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +// Do not remove the include below +#include "Arduino.h" + +#include "logger.h" +#include "ocstack.h" +#include + +#ifdef ARDUINOWIFI +// Arduino WiFi Shield +#include +#include +#include +#else +// Arduino Ethernet Shield +#include +#include +#include +#include +#include +#include +#include +#endif + +#include "easysetup.h" + +const char *getResult(OCStackResult result); + +PROGMEM const char TAG[] = "ArduinoServer"; + +void EventCallbackInApp(ES_RESULT eventFlag) +{ + Serial.println("callback!!! in app"); +} + +// On Arduino Atmel boards with Harvard memory architecture, the stack grows +// downwards from the top and the heap grows upwards. This method will print +// the distance(in terms of bytes) between those two. +// See here for more details : +// http://www.atmel.com/webdoc/AVRLibcReferenceManual/malloc_1malloc_intro.html +void PrintArduinoMemoryStats() +{ +#ifdef ARDUINO_AVR_MEGA2560 + //This var is declared in avr-libc/stdlib/malloc.c + //It keeps the largest address not allocated for heap + extern char *__brkval; + //address of tmp gives us the current stack boundry + int tmp; + OC_LOG_V(INFO, TAG, "Stack: %u Heap: %u", (unsigned int)&tmp, (unsigned int)__brkval); + OC_LOG_V(INFO, TAG, "Unallocated Memory between heap and stack: %u", + ((unsigned int)&tmp - (unsigned int)__brkval)); +#endif +} +//The setup function is called once at startup of the sketch +void setup() +{ + // Add your initialization code here + // Note : This will initialize Serial port on Arduino at 115200 bauds + OC_LOG_INIT(); + OC_LOG(DEBUG, TAG, PCF("OCServer is starting...")); + + WaitingForOnboarding(ES_WIFI, EventCallbackInApp); + + // Initialize the OC Stack in Server mode + if (OCInit(NULL, 0, OC_SERVER) != OC_STACK_OK) + { + OC_LOG(ERROR, TAG, PCF("OCStack init error")); + return; + } + + PrepareToProvisioning(EventCallbackInApp); + + if (OCStartPresence(0) != OC_STACK_OK) + { + OC_LOG(ERROR, TAG, PCF("Start Presence init error")); + return; + } +} + +// The loop function is called in an endless loop +void loop() +{ + // This artificial delay is kept here to avoid endless spinning + // of Arduino microcontroller. Modify it as per specific application needs. + delay(2000); + + // This call displays the amount of free SRAM available on Arduino + PrintArduinoMemoryStats(); + + // Give CPU cycles to OCStack to perform send/recv and other OCStack stuff + if (OCProcess() != OC_STACK_OK) + { + OC_LOG(ERROR, TAG, PCF("OCStack process error")); + return; + } + //ChangeLightRepresentation(NULL); +} diff --git a/service/easy-setup/sdk/arduino/wifi/inc/networkHandler.h b/service/easy-setup/sdk/arduino/wifi/inc/networkHandler.h new file mode 100755 index 0000000..89ee67c --- /dev/null +++ b/service/easy-setup/sdk/arduino/wifi/inc/networkHandler.h @@ -0,0 +1,76 @@ +//****************************************************************** +// +// Copyright 2014 Samsung Electronics All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +// Do not remove the include below +#include "Arduino.h" + +#include "logger.h" +#include "ocstack.h" +#include + +#ifdef ARDUINOWIFI +// Arduino WiFi Shield +#include +#include +#include +#else +// Arduino Ethernet Shield +#include +#include +#include +#include +#include +#include +#include +#endif + +#include "common.h" + +#ifndef ES_NETWORK_HANDLER_H_ +#define ES_NETWORK_HANDLER_H_ + +#define MAXSSIDLEN 33 +#define MAXNETCREDLEN 20 +#define MAXNUMTYPE 5 +#define MAXADDRLEN 15 + +typedef void (*NetworkEventCallback)(ES_RESULT); + +enum NetworkType +{ + ES_WIFI = 1, ES_BT = 2, ES_BLE = 3, ES_ZIGBEE = 4, ES_ETH = 5 +}; + +typedef struct NETWORKINFO +{ + NetworkType type; + + // for WiFI + IPAddress ipaddr; + char ssid[MAXSSIDLEN]; + + // for BT, BLE + byte mac[6]; +} NetworkInfo; + +ES_RESULT ConnectToWiFiNetworkForOnboarding(char *ssid, char *pass, NetworkEventCallback); +int getCurrentNetworkInfo(NetworkType targetType, NetworkInfo *info); + +#endif diff --git a/service/easy-setup/sdk/arduino/wifi/src/networkHandler.cpp b/service/easy-setup/sdk/arduino/wifi/src/networkHandler.cpp new file mode 100755 index 0000000..9fef111 --- /dev/null +++ b/service/easy-setup/sdk/arduino/wifi/src/networkHandler.cpp @@ -0,0 +1,185 @@ +//****************************************************************** +// +// Copyright 2014 Samsung Electronics All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#include "networkHandler.h" + +PROGMEM const char TAG[] = "ArduinoServer"; + +int findNetwork(char *ssid); +int ConnectToNetwork(char *ssid, char *pass); +void printEncryptionType(int thisType); + +// Arduino WiFi Shield +// Note : Arduino WiFi Shield currently does NOT support multicast and therefore +// this server will NOT be listening on 224.0.1.187 multicast address. + +static const char ARDUINO_WIFI_SHIELD_UDP_FW_VER[] = "1.1.0"; + +IPAddress myIP; + +ES_RESULT ConnectToWiFiNetworkForOnboarding(char *ssid, char *pass, NetworkEventCallback cb) +{ + char *fwVersion; + int status = WL_IDLE_STATUS; + int res; + + // check for the presence of the shield: + if (WiFi.status() == WL_NO_SHIELD) + { + OC_LOG(ERROR, TAG, PCF("WiFi shield not present")); + return ES_ERROR; + } + + // Verify that WiFi Shield is running the firmware with all UDP fixes + fwVersion = WiFi.firmwareVersion(); + OC_LOG_V(INFO, TAG, "WiFi Shield Firmware version %s", fwVersion); + if (strncmp(fwVersion, ARDUINO_WIFI_SHIELD_UDP_FW_VER, sizeof(ARDUINO_WIFI_SHIELD_UDP_FW_VER)) + != 0) + { + OC_LOG(DEBUG, TAG, PCF("!!!!! Upgrade WiFi Shield Firmware version !!!!!!")); + return ES_ERROR; + } + + while (findNetwork(ssid) == 0) // found + { + delay(2000); + } + + if (cb != NULL) + { + cb(ES_NETWORKFOUND); + } + + if (WiFi.status() == WL_CONNECTED) + WiFi.disconnect(); + + res = ConnectToNetwork(ssid, pass); + + if (res == 0) + { + return ES_NETWORKCONNECTED; + } + else + { + return ES_NETWORKNOTCONNECTED; + } +} + +int findNetwork(char *ssid) +{ + int res = 0; + // scan for nearby networks: + Serial.println("** Scan Networks **"); + int numSsid = WiFi.scanNetworks(); + if (numSsid == -1) + { + Serial.println("Couldn't get a wifi connection"); + + return res; + } + + // print the list of networks seen: + Serial.print("number of available networks:"); + Serial.println(numSsid); + + // print the network number and name for each network found: + for (int thisNet = 0; thisNet < numSsid; thisNet++) + { + Serial.print(thisNet); + Serial.print(") "); + Serial.print(WiFi.SSID(thisNet)); + Serial.print("\tEncryption: "); + printEncryptionType(WiFi.encryptionType(thisNet)); + + if (strcmp(WiFi.SSID(thisNet), ssid) == 0) + { + res = 1; + } + } + + return res; +} + +int ConnectToNetwork(char *ssid, char *pass) +{ + int status = WL_IDLE_STATUS; + //IPAddress desiredIP(192, 168, 43, 2); + //IPAddress desiredIP(192, 168, 0, 115); + + //WiFi.config(desiredIP); + + // attempt to connect to Wifi network: + while (status != WL_CONNECTED) + { + OC_LOG_V(INFO, TAG, "Attempting to connect to SSID: %s", ssid); + + status = WiFi.begin(ssid, pass); + + // wait 10 seconds for connection: + delay(10000); + } + OC_LOG(DEBUG, TAG, PCF("Connected to wifi")); + + myIP = WiFi.localIP(); + OC_LOG_V(INFO, TAG, "IP Address: %d.%d.%d.%d", myIP[0], myIP[1], myIP[2], myIP[3]); + + char buf[50]; + sprintf(buf, "IP Address: %d.%d.%d.%d", myIP[0], myIP[1], myIP[2], myIP[3]); + Serial.println(buf); + + return 0; +} + +int getCurrentNetworkInfo(NetworkType targetType, NetworkInfo *info) +{ + if (targetType == ES_WIFI && WiFi.status() == WL_CONNECTED) + { + info->type = ES_WIFI; + info->ipaddr = WiFi.localIP(); + strcpy(info->ssid, WiFi.SSID()); + + return 0; + } + + return -1; +} + +void printEncryptionType(int thisType) +{ + // read the encryption type and print out the name: + switch (thisType) + { + case ENC_TYPE_WEP: + Serial.println("WEP"); + break; + case ENC_TYPE_TKIP: + Serial.println("WPA"); + break; + case ENC_TYPE_CCMP: + Serial.println("WPA2"); + break; + case ENC_TYPE_NONE: + Serial.println("None"); + break; + case ENC_TYPE_AUTO: + Serial.println("Auto"); + break; + } +} diff --git a/service/easy-setup/sdk/inc/common.h b/service/easy-setup/sdk/inc/common.h new file mode 100755 index 0000000..3a6fd16 --- /dev/null +++ b/service/easy-setup/sdk/inc/common.h @@ -0,0 +1,38 @@ +//****************************************************************** +// +// Copyright 2014 Samsung Electronics All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#ifndef ES_COMMON_H_ +#define ES_COMMON_H_ + +typedef enum +{ + ES_ERROR = -1, + ES_OK = 0, + ES_NETWORKFOUND = 1, + ES_NETWORKCONNECTED, + ES_NETWORKNOTCONNECTED, + ES_RESOURCECREATED = 11, + ES_RECVREQOFPROVRES = 21, + ES_RECVREQOFNETRES, + ES_RECVUPDATEOFPROVRES, + ES_RECVTRIGGEROFPROVRES, +} ES_RESULT; + +#endif diff --git a/service/easy-setup/sdk/inc/easysetup.h b/service/easy-setup/sdk/inc/easysetup.h new file mode 100755 index 0000000..665d8e3 --- /dev/null +++ b/service/easy-setup/sdk/inc/easysetup.h @@ -0,0 +1,56 @@ +//****************************************************************** +// +// Copyright 2014 Samsung Electronics All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +// Do not remove the include below +#include "Arduino.h" + +#include "logger.h" +#include "ocstack.h" +#include + +#ifdef ARDUINOWIFI +// Arduino WiFi Shield +#include +#include +#include +#else +// Arduino Ethernet Shield +#include +#include +#include +#include +#include +#include +#include +#endif + +#include "common.h" +#include "networkHandler.h" +#include "resourceHandler.h" + +typedef void (*EventCallback)(ES_RESULT); + +OCStackResult Init(); + +ES_RESULT WaitingForOnboarding(NetworkType networkType, EventCallback); +//OCStackResult WaitingForOnboarding(NetworkType networkType, char *name); +//OCStackResult WaitingForOnboarding(NetworkType networkType, char *name, char *pass); + +ES_RESULT PrepareToProvisioning(EventCallback); diff --git a/service/easy-setup/sdk/inc/resourceHandler.h b/service/easy-setup/sdk/inc/resourceHandler.h new file mode 100755 index 0000000..cae38ce --- /dev/null +++ b/service/easy-setup/sdk/inc/resourceHandler.h @@ -0,0 +1,78 @@ +//****************************************************************** +// +// Copyright 2014 Samsung Electronics All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +// Do not remove the include below +#include "Arduino.h" + +#include "logger.h" +#include "ocstack.h" +#include + +#ifdef ARDUINOWIFI +// Arduino WiFi Shield +#include +#include +#include +#else +// Arduino Ethernet Shield +#include +#include +#include +#include +#include +#include +#include +#endif + +#include "common.h" +#include "networkHandler.h" +#include "octypes.h" + +#ifndef ES_RESOURCE_HANDLER_H_ +#define ES_RESOURCE_HANDLER_H_ + +typedef void (*ResourceEventCallback)(ES_RESULT); + +/* Structure to represent a Light resource */ +typedef struct PROVRESOURCE +{ + OCResourceHandle handle; + int ps; // provisiong status, 1 : need to provisioning, 2 : Connected to Internet + int tnt; // target network type, 1: WLAN, 2: BT, 3: BLE, 4: Zigbee, ... + char tnn[MAXSSIDLEN]; // target network name, i.e. SSID for WLAN, MAC address for BT + char cd[MAXNETCREDLEN]; // credential information +} ProvResource; + +/* Structure to represent a Light resource */ +typedef struct NETRESOURCE +{ + OCResourceHandle handle; + int cnt; // current network type, 1: WLAN, 2: BT, 3: BLE, 4: Zigbee, ... + int ant[MAXNUMTYPE]; // available network type, 1: WLAN, 2: BT, 3: BLE, 4: Zigbee, ... + char ipaddr[MAXADDRLEN]; // ip address + char cnn[MAXSSIDLEN]; // current network name +} NetResource; + +OCStackResult createProvisioningResource(); +OCStackResult createNetworkResource(); +void getTargetNetworkInfoFromProvResource(char *, char *); +void RegisterResourceEventCallBack(ResourceEventCallback); + +#endif diff --git a/service/easy-setup/sdk/src/easysetup.cpp b/service/easy-setup/sdk/src/easysetup.cpp new file mode 100755 index 0000000..0706b52 --- /dev/null +++ b/service/easy-setup/sdk/src/easysetup.cpp @@ -0,0 +1,129 @@ +//****************************************************************** +// +// Copyright 2014 Samsung Electronics All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#include "easysetup.h" + +PROGMEM const char TAG[] = "ArduinoServer"; + +/// WiFi network info and credentials +char defaultSsid[] = "EasyConnect"; +char defaultPass[] = "EasyConnect"; + +int g_eventflag = 0; +int g_cnt = 0; +char *targetSsid; +char *targetPass; + +EventCallback g_cbForProvisioning = NULL; +EventCallback g_cbForOnboarding = NULL; + +void EventCallbackInOnboarding(ES_RESULT event); +void EventCallbackInProvisioning(ES_RESULT event); +void EventCallbackAfterProvisioning(ES_RESULT event); + +void EventCallbackInOnboarding(ES_RESULT event) +{ + Serial.println("[Callback] in onboarding process"); + + if (event == ES_NETWORKFOUND || event == ES_NETWORKCONNECTED) + { + if (g_cbForOnboarding != NULL) + { + g_cbForOnboarding(event); + } + } +} + +void EventCallbackInProvisioning(ES_RESULT event) +{ + ES_RESULT res = ES_OK; + + Serial.println("[Callback] in provisioning process"); + + if (event == ES_RECVTRIGGEROFPROVRES) + { + targetSsid = (char *) malloc(MAXSSIDLEN); + targetPass = (char *) malloc(MAXNETCREDLEN); + + getTargetNetworkInfoFromProvResource(targetSsid, targetPass); + + res = ConnectToWiFiNetworkForOnboarding(targetSsid, targetPass, + EventCallbackAfterProvisioning); + + if (g_cbForProvisioning != NULL) + { + g_cbForProvisioning(res); + } + } +} + +void EventCallbackAfterProvisioning(ES_RESULT event) +{ + Serial.println("[Callback] after provisioning process"); + + if (event == ES_NETWORKFOUND || event == ES_NETWORKCONNECTED) + { + if (g_cbForProvisioning != NULL) + { + g_cbForProvisioning(event); + } + } +} + +ES_RESULT WaitingForOnboarding(NetworkType networkType, EventCallback cb) +{ + if (networkType == ES_WIFI) + { + if (g_cbForOnboarding == NULL) + { + g_cbForOnboarding = cb; + } + + return ConnectToWiFiNetworkForOnboarding(defaultSsid, defaultPass, + EventCallbackInOnboarding); + } +} + +ES_RESULT PrepareToProvisioning(EventCallback cb) +{ + if (cb == NULL) + { + return ES_ERROR; + } + else + { + g_cbForProvisioning = cb; + } + + if (createProvisioningResource() != OC_STACK_OK) + { + return ES_ERROR; + } + + if (createNetworkResource() != OC_STACK_OK) + { + return ES_ERROR; + } + + RegisterResourceEventCallBack(EventCallbackInProvisioning); + + return ES_RESOURCECREATED; +} + diff --git a/service/easy-setup/sdk/src/resourceHandler.cpp b/service/easy-setup/sdk/src/resourceHandler.cpp new file mode 100755 index 0000000..d220960 --- /dev/null +++ b/service/easy-setup/sdk/src/resourceHandler.cpp @@ -0,0 +1,404 @@ +//****************************************************************** +// +// Copyright 2014 Samsung Electronics All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#include "resourceHandler.h" +#include "cJSON.h" + +PROGMEM const char TAG[] = "ArduinoServer"; + +ProvResource g_prov; +NetResource g_net; + +OCEntityHandlerResult OCEntityHandlerCb(OCEntityHandlerFlag, OCEntityHandlerRequest *); +const char *getResult(OCStackResult result); + +OCEntityHandlerResult ProcessGetRequest(OCEntityHandlerRequest *ehRequest, char *payload, + uint16_t maxPayloadSize); +OCEntityHandlerResult ProcessPutRequest(OCEntityHandlerRequest *ehRequest, char *payload, + uint16_t maxPayloadSize); +OCEntityHandlerResult ProcessPostRequest(OCEntityHandlerRequest *ehRequest, char *payload, + uint16_t maxPayloadSize); +char* constructJsonResponse(OCEntityHandlerRequest *ehRequest); + +int g_flag = 0; + +ResourceEventCallback g_cbForResEvent = NULL; + +void RegisterResourceEventCallBack(ResourceEventCallback cb) +{ + g_cbForResEvent = cb; +} + +void getTargetNetworkInfoFromProvResource(char *name, char *pass) +{ + if (name != NULL && pass != NULL) + { + sprintf(name, "%s", g_prov.tnn); + sprintf(pass, "%s", g_prov.cd); + } +} + +OCStackResult createProvisioningResource() +{ + g_prov.ps = 1; // need to provisioning + g_prov.tnt = ES_WIFI; + sprintf(g_prov.tnn, "Unknown"); + sprintf(g_prov.cd, "Unknown"); + + OCStackResult res = OCCreateResource(&g_prov.handle, "oic.prov", OC_RSRVD_INTERFACE_DEFAULT, + "/oic/prov", OCEntityHandlerCb, OC_DISCOVERABLE | OC_OBSERVABLE); + + OC_LOG_V(INFO, TAG, "Created Prov resource with result: %s", getResult(res)); + + return res; +} + +OCStackResult createNetworkResource() +{ + NetworkInfo netInfo; + + if (getCurrentNetworkInfo(ES_WIFI, &netInfo) != 0) + { + return OC_STACK_ERROR; + } + + if (netInfo.type != ES_WIFI) + { + return OC_STACK_ERROR; + } + + g_net.cnt = (int) netInfo.type; + g_net.ant[0] = (int) ES_WIFI; + sprintf(g_net.ipaddr, "%d.%d.%d.%d", netInfo.ipaddr[0], netInfo.ipaddr[1], netInfo.ipaddr[2], + netInfo.ipaddr[3]); + sprintf(g_net.cnn, "%s", netInfo.ssid); + + OC_LOG_V(INFO, TAG, "SSID: %s", g_net.cnn); + OC_LOG_V(INFO, TAG, "IP Address: %s", g_net.ipaddr); + + OCStackResult res = OCCreateResource(&g_net.handle, "oic.net", OC_RSRVD_INTERFACE_DEFAULT, + "/oic/net", OCEntityHandlerCb, OC_DISCOVERABLE | OC_OBSERVABLE); + OC_LOG_V(INFO, TAG, "Created Net resource with result: %s", getResult(res)); + + return res; +} + +OCEntityHandlerResult ProcessGetRequest(OCEntityHandlerRequest *ehRequest, char *payload, + uint16_t maxPayloadSize) +{ + OCEntityHandlerResult ehResult = OC_EH_ERROR; + + char *getResp = constructJsonResponse(ehRequest); + + if (!getResp) + { + OC_LOG(ERROR, TAG, "constructJsonResponse failed"); + return OC_EH_ERROR; + } + + if (MAX_RESPONSE_LENGTH > strlen(getResp)) + { + strncpy(payload, getResp, strlen(getResp)); + ehResult = OC_EH_OK; + } + else + { + OC_LOG_V(INFO, TAG, "Response buffer: %d bytes is too small", maxPayloadSize); + ehResult = OC_EH_ERROR; + } + + free(getResp); + + return ehResult; +} + +OCEntityHandlerResult ProcessPutRequest(OCEntityHandlerRequest *ehRequest, char *payload, + uint16_t maxPayloadSize) +{ + OCEntityHandlerResult ehResult = OC_EH_ERROR; + + OC_LOG_V(INFO, TAG, "PUT Request Payload: %s", ehRequest->reqJSONPayload); + + // Get cJSON pointer to query + cJSON *putJson = cJSON_Parse(ehRequest->reqJSONPayload); + if (!putJson) + { + OC_LOG_V(ERROR, TAG, "Failed to parse JSON: %s", ehRequest->reqJSONPayload); + return ehResult; + } + + // Get root of JSON payload, then the 1st resource. + cJSON* carrier = cJSON_GetObjectItem(putJson, "oic"); + if (!carrier) + { + OC_LOG_V(ERROR, TAG, "Failed to parse JSON: %s", ehRequest->reqJSONPayload); + return ehResult; + } + carrier = cJSON_GetArrayItem(carrier, 0); + carrier = cJSON_GetObjectItem(carrier, "rep"); + if (!carrier) + { + OC_LOG_V(ERROR, TAG, "Failed to parse JSON: %s", ehRequest->reqJSONPayload); + return ehResult; + } + + cJSON* prop = cJSON_GetObjectItem(carrier, "tnn"); + if (prop) + { + sprintf(g_prov.tnn, "%s", prop->valuestring); + } + + prop = cJSON_GetObjectItem(carrier, "cd"); + if (prop) + { + sprintf(g_prov.cd, "%s", prop->valuestring); + } + + cJSON_Delete(putJson); + + // TODO: Now once receiving PUT request, the enrollee start to connect to enroller. + g_flag = 1; + + char *getResp = constructJsonResponse(ehRequest); + + if (!getResp) + { + OC_LOG(ERROR, TAG, "constructJsonResponse failed"); + return OC_EH_ERROR; + } + + if (MAX_RESPONSE_LENGTH > strlen(getResp)) + { + strncpy(payload, getResp, strlen(getResp)); + ehResult = OC_EH_OK; + } + else + { + OC_LOG_V(INFO, TAG, "Response buffer: %d bytes is too small", maxPayloadSize); + ehResult = OC_EH_ERROR; + } + + free(getResp); + return ehResult; +} + +OCEntityHandlerResult ProcessPostRequest(OCEntityHandlerRequest *ehRequest, char *payload, + uint16_t maxPayloadSize) +{ + OCEntityHandlerResult ehResult = OC_EH_ERROR; + OC_LOG_V(INFO, TAG, "PUT Request Payload: %s", ehRequest->reqJSONPayload); + + // Get cJSON pointer to query + cJSON *putJson = cJSON_Parse(ehRequest->reqJSONPayload); + + if (!putJson) + { + OC_LOG_V(ERROR, TAG, "Failed to parse JSON: %s", ehRequest->reqJSONPayload); + return ehResult; + } + + // Get root of JSON payload, then the 1st resource. + cJSON* carrier = cJSON_GetObjectItem(putJson, "oic"); + if (!carrier) + { + OC_LOG_V(ERROR, TAG, "Failed to parse JSON: %s", ehRequest->reqJSONPayload); + return ehResult; + } + carrier = cJSON_GetArrayItem(carrier, 0); + carrier = cJSON_GetObjectItem(carrier, "rep"); + if (!carrier) + { + OC_LOG_V(ERROR, TAG, "Failed to parse JSON: %s", ehRequest->reqJSONPayload); + return ehResult; + } + + cJSON* prop = cJSON_GetObjectItem(carrier, "tr"); + if (prop) + { + // Triggering + ehResult = OC_EH_OK; + } + + cJSON_Delete(putJson); + + g_flag = 1; + + return ehResult; +} + +char* constructJsonResponse(OCEntityHandlerRequest *ehRequest) +{ + cJSON *json = cJSON_CreateObject(); + cJSON *format; + char *jsonResponse; + char *JsonResp; + char temp_resp[256]; + + if (g_prov.handle != NULL && ehRequest->resource == g_prov.handle) + { + char *uri = (char *) "/oic/prov"; + + cJSON_AddStringToObject(json, "href", uri); + cJSON_AddItemToObject(json, "rep", format = cJSON_CreateObject()); + cJSON_AddNumberToObject(format, "ps", g_prov.ps); + cJSON_AddNumberToObject(format, "tnt", g_prov.tnt); + cJSON_AddStringToObject(format, "tnn", g_prov.tnn); + cJSON_AddStringToObject(format, "cd", g_prov.cd); + + jsonResponse = cJSON_Print(json); + cJSON_Delete(json); + } + else if (g_net.handle != NULL && ehRequest->requestHandle == g_net.handle) + { + char *uri = (char *) "/oic/net"; + + cJSON_AddStringToObject(json, "href", uri); + cJSON_AddItemToObject(json, "rep", format = cJSON_CreateObject()); + cJSON_AddNumberToObject(format, "ant", g_net.ant[0]); + + jsonResponse = cJSON_Print(json); + cJSON_Delete(json); + } + else + { + return jsonResponse; + } + + OC_LOG_V(INFO, TAG, "Constructed Response: %s", jsonResponse); + + Serial.print("Constructed Response: "); + Serial.println(jsonResponse); + + return jsonResponse; +} + +// This is the entity handler for the registered resource. +// This is invoked by OCStack whenever it recevies a request for this resource. + +OCEntityHandlerResult OCEntityHandlerCb(OCEntityHandlerFlag flag, + OCEntityHandlerRequest* entityHandlerRequest) +{ + OCEntityHandlerResult ehRet = OC_EH_OK; + OCEntityHandlerResponse response = + { 0 }; + char payload[MAX_RESPONSE_LENGTH] = + { 0 }; + + if (entityHandlerRequest && (flag & OC_REQUEST_FLAG)) + { + if (OC_REST_GET == entityHandlerRequest->method) + { + OC_LOG_V(INFO, TAG, "Received GET request"); + ehRet = ProcessGetRequest(entityHandlerRequest, payload, sizeof(payload) - 1); + } + else if (OC_REST_PUT == entityHandlerRequest->method) + { + OC_LOG_V(INFO, TAG, "Received PUT request"); + + if (g_prov.handle != NULL && entityHandlerRequest->resource == g_prov.handle) + { + ehRet = ProcessPutRequest(entityHandlerRequest, payload, sizeof(payload) - 1); + } + else + { + ehRet = OC_EH_ERROR; + } + } + else if (OC_REST_POST == entityHandlerRequest->method) + { + // TODO: As of now, POST request will be not received. + OC_LOG(INFO, TAG, "Received OC_REST_POST from client"); + //ehRet = ProcessPostRequest (entityHandlerRequest, payload, sizeof(payload) - 1); + } + + if (ehRet == OC_EH_OK) + { + // Format the response. Note this requires some info about the request + response.requestHandle = entityHandlerRequest->requestHandle; + response.resourceHandle = entityHandlerRequest->resource; + response.ehResult = ehRet; + response.payload = payload; + response.payloadSize = strlen(payload); + response.numSendVendorSpecificHeaderOptions = 0; + memset(response.sendVendorSpecificHeaderOptions, 0, + sizeof response.sendVendorSpecificHeaderOptions); + memset(response.resourceUri, 0, sizeof response.resourceUri); + // Indicate that response is NOT in a persistent buffer + response.persistentBufferFlag = 0; + + // Send the response + if (OCDoResponse(&response) != OC_STACK_OK) + { + OC_LOG(ERROR, TAG, "Error sending response"); + ehRet = OC_EH_ERROR; + } + } + } + + if (g_flag == 1) + { + g_cbForResEvent(ES_RECVTRIGGEROFPROVRES); + g_flag = 0; + } + + return ehRet; +} + +const char *getResult(OCStackResult result) +{ + switch (result) + { + case OC_STACK_OK: + return "OC_STACK_OK"; + case OC_STACK_INVALID_URI: + return "OC_STACK_INVALID_URI"; + case OC_STACK_INVALID_QUERY: + return "OC_STACK_INVALID_QUERY"; + case OC_STACK_INVALID_IP: + return "OC_STACK_INVALID_IP"; + case OC_STACK_INVALID_PORT: + return "OC_STACK_INVALID_PORT"; + case OC_STACK_INVALID_CALLBACK: + return "OC_STACK_INVALID_CALLBACK"; + case OC_STACK_INVALID_METHOD: + return "OC_STACK_INVALID_METHOD"; + case OC_STACK_NO_MEMORY: + return "OC_STACK_NO_MEMORY"; + case OC_STACK_COMM_ERROR: + return "OC_STACK_COMM_ERROR"; + case OC_STACK_INVALID_PARAM: + return "OC_STACK_INVALID_PARAM"; + case OC_STACK_NOTIMPL: + return "OC_STACK_NOTIMPL"; + case OC_STACK_NO_RESOURCE: + return "OC_STACK_NO_RESOURCE"; + case OC_STACK_RESOURCE_ERROR: + return "OC_STACK_RESOURCE_ERROR"; + case OC_STACK_SLOW_RESOURCE: + return "OC_STACK_SLOW_RESOURCE"; + case OC_STACK_NO_OBSERVERS: + return "OC_STACK_NO_OBSERVERS"; + case OC_STACK_ERROR: + return "OC_STACK_ERROR"; + default: + return "UNKNOWN"; + } +} + -- 2.7.4