--- /dev/null
+CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
+
+SET(CMAKE_VERBOSE_MAKEFILE 0)
+
+PROJECT(${P_NAME} C)
+SET(INSTALL_EXEC_PREFIX "${INSTALL_PREFIX}/bin")
+SET(PROJECT_ROOT_DIR "${CMAKE_SOURCE_DIR}")
+SET(PROJECT_RESOURCES_DIR "${PROJECT_ROOT_DIR}/res")
+SET(CMAKE_INSTALL_RPATH "${INSTALL_PREFIX}/lib")
+
+INCLUDE(FindPkgConfig)
+pkg_check_modules(APP_PKGS REQUIRED
+ dlog
+ capi-appfw-service-application
+ capi-system-peripheral-io
+ capi-media-camera
+ capi-media-vision
+ capi-media-image-util
+ libtzplatform-config
+ glib-2.0
+ gio-2.0
+ ecore
+ rpc-port
+ libexif
+ capi-appfw-package-manager
+)
+
+FOREACH (flag ${APP_PKGS_CFLAGS})
+ SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}")
+ENDFOREACH(flag)
+
+
+SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -fvisibility=hidden -Wall -Winline -g -fno-builtin-malloc -fPIE")
+SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}")
+SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed -pie")
+
+LINK_DIRECTORIES(${PROJECT_ROOT_DIR}/lib)
+SET(ST_API_LIBS st_thing_master_api st_thing_resource_api)
+
+INCLUDE_DIRECTORIES(${PROJECT_ROOT_DIR}/include)
+
+FILE(GLOB APP_SOURCE ${CMAKE_CURRENT_SOURCE_DIR}/src/*.c)
+
+ADD_EXECUTABLE(${PROJECT_NAME} ${APP_SOURCE})
+TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${APP_PKGS_LDFLAGS} -lm ${ST_API_LIBS})
+
+CONFIGURE_FILE(${PROJECT_ROOT_DIR}/tizen-manifest.xml.in ${PROJECT_NAME}.xml @ONLY)
+
+# Install
+INSTALL(TARGETS ${PROJECT_NAME} DESTINATION ${INSTALL_EXEC_PREFIX})
+INSTALL(FILES ${PROJECT_NAME}.xml DESTINATION ${SYS_PACKAGES_DIR})
+INSTALL(DIRECTORY ${PROJECT_ROOT_DIR}/lib DESTINATION ${INSTALL_PREFIX})
+INSTALL(FILES ${PROJECT_ROOT_DIR}/shared/res/default_icon.png DESTINATION ${APP_SHARED_RES_DIR} RENAME ${PROJECT_NAME}.png)
+INSTALL(DIRECTORY ${PROJECT_ROOT_DIR}/res DESTINATION ${INSTALL_PREFIX})
+INSTALL(FILES ${PROJECT_ROOT_DIR}/shared/res/master.json DESTINATION ${APP_SHARED_RES_DIR})
+INSTALL(FILES ${PROJECT_ROOT_DIR}/shared/res/resource.json DESTINATION ${APP_SHARED_RES_DIR})
+INSTALL(DIRECTORY ${PROJECT_ROOT_DIR}/dashboard DESTINATION ${DASH_BOARD_DIR})
--- /dev/null
+Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright 2018 Samsung Electronics Co., Ltd.
+
+ 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.
--- /dev/null
+Copyright (c) 2018 Samsung Electronics Co., Ltd. All rights reserved.
--- /dev/null
+# IoT Vision App
+Analyze images captured by USB camera and then move camera angle by using servo motors.
+
+## HOW TO RUN - First run
+
+### 1. Flash binary
+Tizen 5.0 M2 IoT 부트 이미지 다운로드 [[링크](http://download.tizen.org/releases/milestone/tizen/unified/tizen-unified_20181024.1/images/standard/iot-boot-armv7l-artik533s/)]
+
+Tizen 5.0 M2 Iot Headed 이미지 다운로드 [[링크](http://download.tizen.org/releases/milestone/tizen/unified/tizen-unified_20181024.1/images/standard/iot-headed-3parts-armv7l-artik530_710/)]
+```
+sudo minicom
+ thordown
+lthor tizen-unified_20181024.1_iot-boot-armv7l-artik533s.tar.gz tizen-unified_20181024.1_iot-headed-3parts-armv7l-artik530_710.tar.gz
+```
+
+### 2. Install plug-in
+
+ARTIK 530(5.0) Plugin download from https://developer.samsung.com/tizendevice/firmware
+
+
+### 3. Install Wifi util (*optional)
+Tizen 5.0 M2 wifi-manager-tool 다운로드 [[링크](http://download.tizen.org/releases/milestone/tizen/unified/tizen-unified_20181024.1/repos/standard/packages/armv7l/capi-network-wifi-manager-tool-1.0.39-81.5.armv7l.rpm)]
+```
+sdb root on; sdb shell 'mount -o remount,rw /'
+
+sdb push capi-network-wifi-manager-tool-1.0.39-81.5.armv7l.rpm /tmp
+
+sdb shell 'rpm -ivh /tmp/capi-network-wifi-manager-tool-1.0.39-81.5.armv7l.rpm'
+```
+
+### 4. Build and install custom version of IoT.js to include WebSocket feature
+```
+git clone https://github.com/Samsung/iotjs.git
+
+cd iotjs
+
+sed -i 's/Release: 0/Release: 99/' config/tizen/packaging/iotjs.spec
+
+sed -i '/--no-parallel-build/a \ \ --cmake-param=-DENABLE_MODULE_WEBSOCKET=ON \\' config/tizen/packaging/iotjs.spec
+
+git diff config/tizen/packaging/iotjs.spec
+
+./config/tizen/gbsbuild.sh --clean
+
+sdb push ~/GBS-ROOT/local/repos/tizen_unified_m1/armv7l/RPMS/iotjs-1.0.0-9.0.armv7l.rpm /tmp
+
+sdb shell 'cd /tmp; rpm -ivh iotjs-1.0.0-9.0.armv7l.rpm'
+```
+- https://github.com/Samsung/iotjs/wiki/Build-for-RPi3-Tizen
+- https://github.com/Samsung/iotjs/blob/master/docs/api/IoT.js-API-WebSocket.md
+
+
+### 5. Change camera setting
+```
+sdb shell "cat /etc/multimedia/mmfw_camcorder_camera0.ini | grep 640"
+
+sdb shell "sed -i 's/640,480/320,240/g' /etc/multimedia/mmfw_camcorder_camera0.ini"
+
+sdb shell "cat /etc/multimedia/mmfw_camcorder_camera0.ini | grep 320"
+```
+
+### 6. Build and install vision app
+```
+git clone git://git.tizen.org/apps/native/smart-surveillance-camera # This git
+
+cd smart-surveillance-camera
+
+gbs build -A armv7l --include-all
+
+sdb push ~/GBS-ROOT/local/BUILD-ROOTS/scratch.armv7l.0/home/abuild/rpmbuild/RPMS/armv7l/iot-vision-camera-0.0.1-1.armv7l.rpm /tmp
+
+sdb shell 'rpm -ivh --force /tmp/iot-vision-camera-0.0.1-1.armv7l.rpm'
+```
+### 7. Some more settings
+```
+sdb shell 'pkg_initdb'
+```
+### 8. Launch vision app
+```
+sdb shell 'app_launcher -s iot-vision-camera'
+```
+### 9. Check vision app activity
+```
+sdb shell 'ls -l /tmp/latest.jpg'
+```
+### 10. Install and run monitor server
+* If you install latest version of "iot-vision-camera" package, the monitor server is automatically launched in booting time
+
+* To check status of the monitor server
+ ```
+ sdb shell 'systemctl status iot-dashboard'
+ ```
+
+* To restart the monitor server
+ ```
+ sdb shell 'systemctl stop iot-dashboard'
+ sdb shell 'systemctl start iot-dashboard'
+ sdb shell 'systemctl status iot-dashboard' # To check status
+ ```
+
+* To update some files of the monitor server, push the files to dashboard path `/opt/home/dashboard` and restart the monitor server as above
+ ```
+ sdb shell push {path/yourfile} /opt/home/dashboard/{path}
+ ```
+OR! YOU CAN SIMPLY USE THE SCRIPT:
+```
+./update-dashboard.sh
+```
+
+
+## HOW TO RUN - Subsequent Runs
+```
+sdb root on; sdb shell 'mount -o remount,rw /'
+
+sdb shell 'app_launcher -s iot-vision-camera'
+
+ ./update-dashboard.sh
+```
+
+## Profiling Data
+
+### 카메라의 물리적 이동시간
+슈퍼슬로우 카메라로 촬영결과 500ms 정도 소요
+
+### Rpi
+
+#### Image Encoding (buffer -> jpg file)
+소요시간 20 ~ 135ms (가끔씩 오래걸림, 장담 못함)
+
+#### Vision Survailance (input -> cb event)
+소요시간 38 ~ 50ms
+
+
+### Artik
+
+#### Image Encoding (buffer -> jpg file)
+소요시간 10 ~ 20ms, 대부분 10ms 초반 안정적
+
+#### Vision Survailance (input -> cb event)
+소요시간 24 ~ 42ms
+
+## Vision 움직임 정보 형식 (exif)
+최대 244Byte 크기의 스트링으로 모두 숫자로 이루어져있다.
+
+첫 2자리 숫자는 분석결과의 타입으로 TT 의 값을 갖는다.
+
+그 다음 2자리 숫자는 포함된 움직임의 갯수 NN 의 값을 갖는다.
+
+하나의 움직임은 8개 숫자로 구성되며 xxyywwhh 의 값을 갖는다.
+
+xx: x 상대 좌표
+yy: y 상대 좌표
+ww: 상대 넓이
+hh: 상대 높이
+
+각각 0~99까지의 범위를 갖는 4개의 숫자를 이어놓은 것이다.
+1자리 숫자의 경우 0을 넣어서 전체 길이를 고정한다.
+
+TTNNxxyywwhhxxyywwhh....xxyywwhh 의 형태의 스트링이 된다.
--- /dev/null
+body {
+ width: 1920px;
+ height: 1080px;
+ overflow-x: hidden;
+ overflow-y: auto;
+}
+
+html {
+ width: 1920px;
+ height: 1080px;
+ overflow-x: hidden;
+ overflow-y: auto;
+}
+
+body {
+ margin: 0;
+ background: url("../image/bg.png") no-repeat fixed;
+ background-size: 1920px 1080px;
+}
+
+#text-container {
+ width: 1200px;
+ color: #ffffff;
+ padding-top: 50px;
+ margin-left: 110px;
+}
+
+#project-title {
+ font: 800 60px 'arial';
+ line-height: 70px;
+}
+
+#project-main-text {
+ font: 500 28px 'arial';
+ line-height: 48px;
+ margin-top: 20px;
+}
+
+ul {
+ list-style-image: url("../image/bullet.png");
+}
+
+li {
+ padding-left: 20px;
+}
+
+.nobull {
+ list-style: none;
+ list-style-type: none;
+ display: inline-block;
+}
+
+.try-it-bullet {
+ margin-left: -65px;
+ position: absolute;
+ font-size: 18px;
+ font-family: 'arial';
+ color: #FBB03B;
+ -ms-transform: rotate(-20deg); /* IE 9 */
+ -webkit-transform: rotate(-20deg); /* Safari */
+ transform: rotate(-20deg);
+}
+
+.shake-it {
+ animation: shake 2s cubic-bezier(.36,.07,.19,.97) both infinite;
+}
+
+@keyframes shake {
+ 10%, 90% { transform: rotate(-20deg) }
+ 20%, 80% { transform: rotate(20deg) }
+ 30%, 50%, 70% { transform: rotate(-20deg) }
+ 40%, 60% { transform: rotate(20deg) }
+}
+
+.blink {
+ -webkit-animation: blink 2.0s linear infinite;
+}
+@-webkit-keyframes blink {
+ 0% { opacity: 1.0; }
+ 10% { opacity: 0.3; }
+ 40% { opacity: 1.0; }
+ 100% { opacity: 1.0; }
+/* from { background-color: red;}
+ to {background-color: green;} */
+}
+
+#diagram-container {
+ width: 1735px;
+ font: 800 36px 'arial';
+ margin: 60px 0 0 70px;
+}
+
+#diagram-bg {
+ position: absolute;
+ margin: 0 0 0 -20px;
+ width: 1020px;
+ height: 400px;
+ background-color: #ffffff;
+ opacity: 0.1;
+}
+
+#diagram-title {
+ font: 500 25px 'arial';
+ color: #FBB03B;
+ padding: 25px 0 0 15px;
+}
+
+.d-text-tizen {
+ color: #F47A0B;
+}
+
+.d-text-st {
+ color: #FBB03B;
+}
+
+.d-text-tizen {
+ text-shadow: 2px 2px 4px #113255;
+}
+
+.d-text-st {
+ text-shadow: 2px 2px 4px #113255;
+}
+
+.caption-text {
+ font: 500 18px 'arial';
+ line-height: 1px;
+ display: block;
+}
+
+.caption-arrow {
+ font: 500 18px 'arial';
+ color: #A9ABAC;
+ line-height: 1px;
+}
+
+.arrow-01 {
+ width: 51px;
+ background: url("../image/arrow-01.png") center no-repeat;
+}
+
+.arrow-02 {
+ width: 46px;
+ background: url("../image/arrow-02.png") no-repeat;
+ background-position: center bottom;
+ margin-bottom: -20px;
+}
+
+.arrow-03 {
+ width: 48px;
+ background: url("../image/arrow-03.png") no-repeat;
+ background-position: center top;
+ margin-top: -20px;
+}
+
+.arrow-04 {
+ width: 67px;
+ background: url("../image/arrow-04.png") center no-repeat;
+}
+
+.arrow-05 {
+ width: 305px;
+ background: url("../image/arrow-05.png") center no-repeat;
+}
+
+.arrow-06 {
+ width: 473px;
+ background: url("../image/arrow-06.png") center no-repeat;
+}
+
+.arrow-04, .arrow-05, .arrow-06 {
+ padding-top: 10px;
+}
+
+.caption-text {
+ margin-top:-10px;
+}
+
+.diagram-main > div {
+ display: inline-block;
+ height: 80px;
+ line-height: 80px;
+ text-align: center;
+ vertical-align: middle;
+ margin-right: 15px;
+}
+
+.two-line {
+ line-height: 40px !important;
+}
+
+#diagram-top {
+ margin: 15px 0 0 330px;
+}
+
+#diagram-middle {
+ margin: 10px 0 0 30px;
+}
+
+#diagram-bottom {
+ margin: 30px 0 0 335px;
+}
+
+#diagram-right {
+ position: absolute;
+ top: 490px;
+ left: 1420px;
+}
+
+#diagram-right > div {
+ position: absolute;
+}
+
+.arrow-07 {
+ width: 129px;
+ height: 361px;
+ background: url("../image/arrow-07.png") center no-repeat;
+ margin: 15px 0 0 -20px;
+}
+
+.arrow-08 {
+ width: 42px;
+ height: 85px;
+ background: url("../image/arrow-08.png") center no-repeat;
+ margin: 400px 0 0 280px;
+}
+
+#mobile {
+ width: 131px;
+ height: 261px;
+ background: url("../image/mobile.png") center no-repeat;
+ margin: 100px 0 0 250px;
+ text-align: center;
+ color: #ffffff;
+ font: 800 18px 'arial';
+}
+
+#mobile-detection {
+ margin-top: 100px;
+}
+
+.smaller-text {
+ font-size: 13px;
+ line-height: 10px;
+}
+
+#mobile-caption {
+ margin-top: 120px;
+}
+
+#camera-container {
+ position: absolute;
+ top: 5px;
+ left: 1100px;
+}
+
+#camera-container > div, img {
+ position: absolute;
+}
+
+#camera-view-bg {
+ z-index:-1;
+ width: 878px;
+ height: 658px;
+ background-image: url("../image/shadow.png");
+}
+
+#camera-view {
+ width: 640px;
+ height: 480px;
+ left: 90px;
+ top: 65px;
+ background-image: url("../image/image.png");
+ outline: 5px solid #FBB03B;
+}
+
+#camera-view-caption {
+ width: 878px;
+ top: 560px;
+ left: -15px;
+}
+
+.image-caption {
+ color: #8FC2F2;
+ font: 800 15px 'arial';
+ text-align: center;
+}
+
+#canvas-container canvas {
+ z-index: 10;
+ position: absolute;
+ left: 90px;
+ top: 65px;
+}
+
+#fps {
+ font-weight: 800;
+}
--- /dev/null
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
+ <meta name="description" content="TEST PAGE">
+ <meta name="author" content="salt">
+
+ <title>Tizen IoT</title>
+
+ <!-- 합쳐지고 최소화된 최신 CSS -->
+ <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css">
+ <link href="css/style.css" rel="stylesheet">
+</head>
+
+<body>
+ <div id="main-container">
+ <div id="text-container">
+ <div id="project-title">Tizen IoT<br>Smart Surveillance Camera</div>
+ <div id="project-main-text">
+ <ul>
+ <li class="step1">Captures images continuously with a USB camera</li>
+ <li class="step2">Detects motion of objects in the images</li>
+ <li class="step3">Controls servomotors to follow the motion</li>
+ <li class="step4">Sends the images to connected web clients</li>
+ <li class="step5">Displays a live view of images in each web client</li>
+ <li class="step6">Sends motion info to SmartThings Cloud</li>
+ <li class="step7">Displays motion info on SmartThings Mobile App</li>
+ <li class="step8 nobull"><span class="try-it-bullet">TRY IT!</span>You can manually control servomotors using the SmartThings Mobile App</li>
+ </ul>
+ </div>
+ </div>
+ <div id="diagram-container">
+ <div id="diagram-bg"></div>
+ <div id="diagram-title">Tizen IoT made in Craftroom</div>
+ <div id="diagram-top" class="diagram-main">
+ <div class="arrow-02 arrow step2"></div>
+ <div class="d-text-tizen step3 step8">Peripheral IO</div>
+ <div class="arrow-04 arrow step3 step8"><span class="caption-arrow">moving</span></div>
+ <div class="d-text-tizen step3 step8">Servomotor</div>
+ </div>
+ <div id="diagram-middle" class="diagram-main">
+ <div class="d-text-tizen step1" id="d-text-camera">Camera<span class="caption-text">capturing</span></div>
+ <div class="arrow-01 arrow step1"></div>
+ <div class="d-text-tizen step2" id="d-text-vision">Vision<span class="caption-text">analysing</span></div>
+ <div class="arrow-01 arrow step2"></div>
+ <div class="d-text-tizen step4">IoT.js</div>
+ <div class="arrow-06 arrow step4"><span class="caption-arrow">live streaming (<span id="fps">0</span> fps)</span></div>
+ <div class="d-text-st step5">Web Client<span class="caption-text">(this screen)</span></div>
+ </div>
+ <div id="diagram-bottom" class="diagram-main">
+ <div class="arrow-03 arrow step2"></div>
+ <div class="d-text-tizen step6 step8">SmartThings SDK</div>
+ <div class="arrow-05 arrow step6 step8"><span class="caption-arrow">transferring</span></div>
+ <div class="d-text-st two-line step6 step8">SmartThings<br>Cloud</div>
+ <div class="arrow-04 arrow step6 step8"></div>
+ <div class="d-text-st two-line step7 step8">SmartThings<br>Mobile App</div>
+ </div>
+ <div id="diagram-right">
+ <div class="arrow-07 arrow step5"></div>
+ <div class="arrow-08 arrow step7 step8"></div>
+ <div id="mobile">
+ <div id="mobile-detection">Motion<br>Detected</div>
+ <div id="mobile-caption" class="image-caption">Mobile Device</div>
+ </div>
+ </div>
+ </div>
+ <div id="camera-container">
+ <div id="canvas-container">
+ <canvas id="camera-view-canvas" width="640" height="480"></canvas>
+ </div>
+ <div id="camera-view-bg"></div>
+ <img id="camera-view"/>
+ <div id="camera-view-caption" class="image-caption">Camera Live View</div>
+ </div>
+ </div>
+ <!-- jQuery -->
+ <script src="https://code.jquery.com/jquery-1.12.4.min.js" integrity="sha256-ZosEbRLbNQzLpnKIkEdrPv7lOy9C27hHQ+Xp8a4MxAQ="
+ crossorigin="anonymous"></script>
+ <!-- 합쳐지고 최소화된 최신 자바스크립트 -->
+ <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/js/bootstrap.min.js"></script>
+
+ <script src="js/app.js"></script>
+ <script src="https://cdn.jsdelivr.net/npm/exif-js"></script>
+</body>
+
+</html>
--- /dev/null
+ /*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ */
+
+const IMG_WIDTH = 640;
+const IMG_HEIGHT = 480;
+const CANVAS_WIDTH = 640;
+const CANVAS_HEIGHT = 480;
+
+window.onload = function(){
+ var canvas;
+ var frame_timestamp = new Array(100);
+ var request_time;
+ var frame_number = 0;
+
+ var xhr = new XMLHttpRequest();
+ xhr.onreadystatechange = function() {
+ var previewElement = document.getElementById('camera-view');
+
+ if (xhr.readyState === 4) {
+ update_fps();
+ // console.log(JSON.stringify(frame_timestamp));
+
+ var latencyTag = document.getElementById('latency');
+ if (latencyTag != null)
+ latencyTag.innerHTML = 'latency: ' + (Date.now() - request_time) + ' ms';
+
+ previewElement.src = xhr.response;
+ }
+ };
+
+ canvas = new Canvas("camera-view-canvas");
+
+ runWebSocket();
+
+ function update_fps() {
+ frame_timestamp[frame_number] = Date.now();
+ var fpsTag = document.getElementById('fps');
+ if (fpsTag != null)
+ fpsTag.innerHTML = JSON.stringify(fps());
+ if (++frame_number == frame_timestamp.length) frame_number = 0;
+ }
+
+ function fps() {
+ var i = frame_number;
+ var now = Date.now();
+ do { // backtrace to find the frame 1000 milliseconds before
+ if (now - frame_timestamp[i] >= 1000) {
+ var fps = frame_number - i;
+ if (fps < 0)
+ fps += frame_timestamp.length;
+ return fps;
+ }
+ if (--i < 0) // wrap around to the last slot in the array
+ i = frame_timestamp.length - 1;
+ } while (i != frame_number)
+ }
+
+ function runWebSocket() {
+ // var wsUri = "ws://192.168.1.211:8888/";
+ var wsUri = "ws://" + window.location.hostname + ":8888/";
+
+ websocket = new WebSocket(wsUri);
+ websocket.onopen = function(evt) { onOpen(evt) };
+ websocket.onclose = function(evt) { onClose(evt) };
+ websocket.onmessage = function(evt) { onMessage(evt) };
+ websocket.onerror = function(evt) { onError(evt) };
+
+ // // polling
+ // setInterval(function() {
+ // // console.log('hey!');
+ // xhr.open('POST', '/requestImage' , true);
+ // xhr.send();
+ // request_time = Date.now();
+ // // console.log('update image');
+ // }, 100);
+ }
+
+ function onOpen(evt)
+ {
+ writeToScreen("CONNECTED");
+ doSend("HELLO FROM BROWSER via WebSocket!!!!!!!!!!!!");
+ }
+
+ function onClose(evt)
+ {
+ writeToScreen("DISCONNECTED");
+ }
+
+ function onMessage(evt)
+ {
+ // writeToScreen('<span style="color: blue;">RESPONSE: ' + evt.data+'</span>');
+
+ var urlCreator = window.URL || window.webkitURL;
+ var imageUrl = urlCreator.createObjectURL(evt.data);
+ document.querySelector("#camera-view").src = imageUrl;
+ update_fps();
+
+ var arrayBuffer;
+ var fileReader = new FileReader();
+ fileReader.onload = function(event) {
+ arrayBuffer = event.target.result;
+ var exif = EXIF.readFromBinaryFile(arrayBuffer);
+ var exifInfoString = asciiToStr(exif.UserComment, 8);
+ var type = 'blur';
+ if (getResultType(exifInfoString) != 0) {
+ type = 'active';
+ }
+
+ var pointArray = getPointArrayFromString(exifInfoString.slice(4));
+
+ if (pointArray.length <= 0) {
+ document.querySelector("#mobile-detection").innerHTML = "No<br>Motion";
+ } else {
+ document.querySelector("#mobile-detection").innerHTML = "Motion<br>Detected";
+ }
+
+ canvas.clearPoints();
+ canvas.drawPoints(pointArray, type);
+ };
+ fileReader.readAsArrayBuffer(evt.data);
+
+ doSend("ack", true);
+
+ // websocket.close();
+
+ // var reader = new FileReader();
+ // reader.readAsDataURL(evt.data);
+ // reader.onloadend = function() {
+ // base64data = reader.result;
+ // var previewElement = document.getElementById('camera-view');
+ // previewElement.src = base64data;
+ // update_fps();
+ // }
+ }
+
+ function onError(evt)
+ {
+ writeToScreen('<span style="color: red;">ERROR:</span> ' + evt.data);
+ }
+
+ function doSend(message, dont_print_log)
+ {
+ websocket.send(message);
+ if (!dont_print_log)
+ writeToScreen("SENT: " + message);
+ }
+
+ function writeToScreen(message)
+ {
+ var output = document.getElementById("output");
+ if (output == null)
+ return;
+ var pre = document.createElement("p");
+ pre.style.wordWrap = "break-word";
+ pre.innerHTML = message;
+ output.appendChild(pre);
+ }
+
+ function asciiToStr(asciiArr, start) {
+ var string = "";
+ var i = start;
+
+ for (; i < asciiArr.length; i++) {
+ string += String.fromCharCode(asciiArr[i]);
+ }
+
+ return string;
+ }
+
+ function getResultType(str) {
+ return Number(str.slice(0, 2));
+ }
+
+ function getPointArrayFromString(pointStr) {
+ var strLen = pointStr.length;
+ var i = 0;
+ var pointArray = [];
+
+ while (i < strLen) {
+ pointArray.push(pointStr.slice(i, i + 8));
+ i += 8;
+ }
+
+ return pointArray;
+ }
+
+ var step = 0
+ const total_steps = 8
+ setInterval(function() {
+ for (var i = 0; i < total_steps; i++) {
+ var className = '.step' + (i + 1);
+ $('li' + className).removeClass('blink');
+ $('.d-text-tizen' + className).removeClass('blink');
+ $('.d-text-st' + className).removeClass('blink');
+ $('.arrow' + className).removeClass('blink');
+ $('.try-it-bullet').removeClass('shake-it');
+ }
+ var className = '.step' + (step + 1);
+ $('li' + className).addClass('blink');
+ $('.d-text-tizen' + className).addClass('blink');
+ $('.d-text-st' + className).addClass('blink');
+ $('.arrow' + className).addClass('blink');
+ if (step == 7)
+ $('.try-it-bullet').addClass('shake-it');
+ step = ++step % total_steps;
+ }, 4000);
+};
+
+function Canvas(canvasId) {
+ this.viewCanvas = document.getElementById(canvasId);
+ this.viewContext = this.viewCanvas.getContext("2d");
+}
+
+Canvas.prototype.clearCanvas = function() {
+ this.viewContext.clearRect(0,0, CANVAS_WIDTH, CANVAS_HEIGHT);
+}
+
+Canvas.prototype.clearPoints = function () {
+ this.clearCanvas();
+}
+
+Canvas.prototype.drawRect = function(x, y, width, height, color) {
+ this.viewContext.beginPath();
+ this.viewContext.moveTo(x, y);
+ this.viewContext.lineTo(x, y + height);
+ this.viewContext.lineTo(x + width, y + height);
+ this.viewContext.lineTo(x + width, y);
+ this.viewContext.closePath();
+ this.viewContext.lineWidth = 3;
+ this.viewContext.strokeStyle = color;
+ this.viewContext.stroke();
+}
+
+Canvas.prototype.drawPoints = function (pointArray, type) {
+ var i = 0;
+ var x, y, w, h;
+ var color;
+
+ if (type == 'blur') {
+ color = "rgba(115,232,57,0.8)";
+ } else {
+ color = "rgba(255,0,0, 0.8)";
+ }
+
+ for (i = 0; i < pointArray.length; i++) {
+ x = IMG_WIDTH / 99 * parseInt(pointArray[i].slice(0,2));
+ y = IMG_HEIGHT / 99 * parseInt(pointArray[i].slice(2,4));
+ w = IMG_WIDTH / 99 * parseInt(pointArray[i].slice(4,6));
+ h = IMG_HEIGHT / 99 * parseInt(pointArray[i].slice(6,8));
+
+ this.drawRect(x, y, w, h, color);
+ }
+}
--- /dev/null
+ /*\r
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an AS IS BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+var fs = require('fs');\r
+var http = require('http');\r
+\r
+function extractPath(url) {\r
+ var urlParts = url.split('/'),\r
+ i = 0,\r
+ l = urlParts.length,\r
+ result = [];\r
+ for (; i < l; ++i) {\r
+ if (urlParts[i].length > 0) {\r
+ result.push(urlParts[i]);\r
+ }\r
+ }\r
+ return result;\r
+}\r
+\r
+http.createServer(function(req, res) {\r
+ req.on('end', function() {\r
+ var path = extractPath(req.url);\r
+ console.log(req.url)\r
+ // var last = path[path.length - 1];\r
+ if (path[0] === undefined) {\r
+ res.writeHead(200);\r
+ res.end(fs.readFileSync('public/index.html'));\r
+ } else if (path[0] == 'test') {\r
+ res.writeHead(200);\r
+ res.end(fs.readFileSync('public/test.html'));\r
+ } else if (req.url == '/js/app.js') {\r
+ res.writeHead(200);\r
+ res.end(fs.readFileSync('public/js/app.js'));\r
+ } else if (req.url == '/css/style.css') {\r
+ res.writeHead(200);\r
+ res.end(fs.readFileSync('public/css/style.css'));\r
+ } else {\r
+ res.setHeader('Location', 'http://download.tizen.online/smart-surveillance' + req.url);\r
+ res.writeHead(302);\r
+ res.end();\r
+ console.log('33333');\r
+ }\r
+ });\r
+}).listen(9090);\r
+\r
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////\r
+\r
+var ENABLE_WEBSOCKET = true;\r
+\r
+if (ENABLE_WEBSOCKET) {\r
+\r
+ var websocket = require('websocket');\r
+\r
+ var options = {\r
+ port: 8888\r
+ }\r
+\r
+ var server = new websocket.Server(options, Listener);\r
+\r
+ function Listener(ws) {\r
+ console.log('Client connected: handshake done!');\r
+ ws.ack = true;\r
+ ws.on('message', function (msg) {\r
+ console.log('Message received: %s', msg.toString());\r
+ // ws.send(msg.toString(), {mask: true, binary: false}); //echo\r
+ // ws.send('Received: ' + msg.toString()); //echo\r
+ // server.close();\r
+ ws.ack = true;\r
+ });\r
+ ws.on('ping', function (msg) {\r
+ console.log('Ping received: %s', msg.toString());\r
+ });\r
+ ws.on('error', function (msg) {\r
+ console.log('Error: %s', msg.toString());\r
+ });\r
+\r
+ var i = 0;\r
+ var prev = 0;\r
+ var timeout = setInterval(function() {\r
+ if (!ws.ack)\r
+ return false;\r
+ var now = Date.now();\r
+ var data;\r
+ try {\r
+ data = fs.readFileSync('/tmp/latest.jpg');\r
+ } catch (err) {\r
+ data = fs.readFileSync('/opt/home/dashboard/default.gif');\r
+ }\r
+ ws.send(data, {mask: false, binary: true});\r
+ console.log(`Sending frame(${i++}), interval(${now - prev} ms)`);\r
+ // server.broadcast(data, {mask: false, binary: true});\r
+ // server.broadcast(`HELLO TO ALL FROM IoT.js!!! (${i++}, ${now - prev})`);\r
+ prev = now;\r
+ ws.ack = false;\r
+ }, 1000 / 15.0);\r
+\r
+ ws.on('close', function (msg) {\r
+ console.log('Client close: ' + msg.reason + ' (' + msg.code + ')');\r
+ clearInterval(timeout);\r
+ });\r
+ };\r
+\r
+ server.on('error', function (msg) {\r
+ console.log('Error: %s', msg.toString());\r
+ });\r
+\r
+ server.on('close', function (msg) {\r
+ console.log('Server close: ' + msg.reason + ' (' + msg.code + ')');\r
+ });\r
+\r
+}\r
--- /dev/null
+ /*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ *
+ * 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 __CONTROLLER_H__
+#define __CONTROLLER_H__
+
+#define MV_RESULT_COUNT_MAX 30
+#define MV_RESULT_LENGTH_MAX (MV_RESULT_COUNT_MAX * 4) //4(x, y, w, h) * COUNT
+#define IMAGE_INFO_MAX ((8 * MV_RESULT_LENGTH_MAX) + 4)
+
+#define IMAGE_WIDTH 320
+#define IMAGE_HEIGHT 240
+#define CAMERA_IMAGE_QUALITY 100 //1~100
+#define CAMERA_PREVIEW_INTERVAL_MIN 50
+
+//카메라와 모터에 따라 최적화 필요한 값 --------------------------------
+#define SERVO_MOTOR_VERTICAL_MIN 20
+#define SERVO_MOTOR_VERTICAL_MAX 45
+#define SERVO_MOTOR_VERTICAL_CENTER ((SERVO_MOTOR_VERTICAL_MIN + SERVO_MOTOR_VERTICAL_MAX) / 2)
+#define SERVO_MOTOR_HORIZONTAL_MIN 30
+#define SERVO_MOTOR_HORIZONTAL_MAX 75
+#define SERVO_MOTOR_HORIZONTAL_CENTER ((SERVO_MOTOR_HORIZONTAL_MIN + SERVO_MOTOR_HORIZONTAL_MAX) / 2)
+
+// 70CM 앞 물체가 화면의 서보모터 이동단위(1/20) 만큼 이동에 필요한 값 (실측)
+#define SERVO_MOTOR_VERTICAL_STEP 1
+#define SERVO_MOTOR_HORIZONTAL_STEP 1.25
+
+#endif
--- /dev/null
+ /*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ *
+ * 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 __CONTROLLER_IMAGE_H__
+#define __CONTROLLER_IMAGE_H__
+
+void controller_image_initialize(void);
+void controller_image_finalize(void);
+int controller_image_save_image_file(const char *path,
+ unsigned int width, unsigned int height, const unsigned char *buffer,
+ const char *comment, unsigned int comment_len);
+int controller_image_read_image_file(const char *path,
+ unsigned int *width, unsigned int *height, unsigned char *buffer, unsigned long long *size);
+#endif
--- /dev/null
+ /*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ *
+ * 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 __CONTROLLER_MV_H__
+#define __CONTROLLER_MV_H__
+#include <mv_common.h>
+
+typedef void (*movement_detected_cb)(int horizontal, int vertical, int result[], int result_count, void *user_data);
+
+mv_source_h controller_mv_create_source(
+ unsigned char *buffer, unsigned int size,
+ unsigned int width, unsigned int height, mv_colorspace_e colorspace);
+void controller_mv_push_source(mv_source_h source);
+int controller_mv_set_movement_detection_event_cb(movement_detected_cb movement_detected_cb, void *user_data);
+void controller_mv_unset_movement_detection_event_cb(void);
+
+#endif
--- /dev/null
+ /*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ *
+ * 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 __APP_EXIF_H__
+#define __APP_EXIF_H__
+
+/* CAUTION
+ * This function is only for adding exif with user comment
+ * to JPEG which has No existing exif data !!!
+ */
+int exif_write_jpg_file_with_comment(const char *output_file,
+ const unsigned char *jpg_data, unsigned int jpg_size,
+ unsigned int jpg_width, unsigned int jpg_height,
+ const char *comment, unsigned int comment_len);
+
+#endif /* __APP_EXIF_H__ */
--- /dev/null
+ /*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ *
+ * 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 __LOG_H__
+#define __LOG_H__
+
+#include <strings.h>
+#include <dlog.h>
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+#define LOG_TAG "SIV"
+
+#if !defined(_D)
+#define _D(fmt, arg...) dlog_print(DLOG_DEBUG, LOG_TAG, "[%s][%s:%d] " fmt "\n", rindex(__FILE__, '/') + 1, __func__, __LINE__, ##arg)
+#endif
+
+#if !defined(_I)
+#define _I(fmt, arg...) dlog_print(DLOG_INFO, LOG_TAG, "[%s][%s:%d] " fmt "\n", rindex(__FILE__, '/') + 1, __func__, __LINE__, ##arg)
+#endif
+
+#if !defined(_W)
+#define _W(fmt, arg...) dlog_print(DLOG_WARN, LOG_TAG, "[%s][%s:%d] " fmt "\n", rindex(__FILE__, '/') + 1, __func__, __LINE__, ##arg)
+#endif
+
+#if !defined(_E)
+#define _E(fmt, arg...) dlog_print(DLOG_ERROR, LOG_TAG, "[%s][%s:%d] " fmt "\n", rindex(__FILE__, '/') + 1, __func__, __LINE__, ##arg)
+#endif
+
+#define retvm_if(expr, val, fmt, arg...) do { \
+ if (expr) { \
+ _E(fmt, ##arg); \
+ _E("(%s) -> %s() return", #expr, __FUNCTION__); \
+ return val; \
+ } \
+} while (0)
+
+#define retv_if(expr, val) do { \
+ if (expr) { \
+ _E("(%s) -> %s() return", #expr, __FUNCTION__); \
+ return (val); \
+ } \
+} while (0)
+
+#define retm_if(expr, fmt, arg...) do { \
+ if (expr) { \
+ _E(fmt, ##arg); \
+ _E("(%s) -> %s() return", #expr, __FUNCTION__); \
+ return; \
+ } \
+} while (0)
+
+#define ret_if(expr) do { \
+ if (expr) { \
+ _E("(%s) -> %s() return", #expr, __FUNCTION__); \
+ return; \
+ } \
+} while (0)
+
+#define goto_if(expr, val) do { \
+ if (expr) { \
+ _E("(%s) -> goto", #expr); \
+ goto val; \
+ } \
+} while (0)
+
+#define break_if(expr) { \
+ if (expr) { \
+ _E("(%s) -> break", #expr); \
+ break; \
+ } \
+}
+
+#define continue_if(expr) { \
+ if (expr) { \
+ _E("(%s) -> continue", #expr); \
+ continue; \
+ } \
+}
+#endif
--- /dev/null
+ /*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ *
+ * 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 __MOTION_H__
+#define __MOTION_H__
+
+typedef void(*motion_state_changed_cb) (int state, void* user_data);
+
+int motion_initialize(void);
+int motion_finalize(void);
+int motion_state_set(int state, const char *pass_key);
+int motion_state_get(int *state);
+int motion_state_changed_cb_set(
+ const char *callback_key, motion_state_changed_cb callback, void *cb_data);
+
+#endif /* __MOTION_H__ */
--- /dev/null
+ /*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ *
+ * 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 __RESOURCE_CAMERA_H__
+#define __RESOURCE_CAMERA_H__
+
+typedef struct __image_buffer_data_s {
+ unsigned char *buffer;
+ unsigned int buffer_size;
+ unsigned int image_width;
+ unsigned int image_height;
+ camera_pixel_format_e format;
+ void *user_data;
+} image_buffer_data_s;
+
+typedef void (*preview_image_buffer_created_cb)(void *buffedata);
+typedef void (*capture_completed_cb)(const void *image, unsigned int size, void *user_data);
+
+int resource_camera_init(preview_image_buffer_created_cb preview_image_buffer_created_cb, void *user_data);
+int resource_camera_start_preview(void);
+int resource_camera_capture(capture_completed_cb capture_completed_cb, void *data);
+void resource_camera_close(void);
+
+#endif
--- /dev/null
+ /*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ *
+ * 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 __RESOURCE_SERVO_MOTOR_SG90_H__
+#define __RESOURCE_SERVO_MOTOR_SG90_H__
+
+void resource_close_servo_motor(int channel);
+
+/**
+ * This module is sample codes to handling Servo motors in Tizen platform.
+ * Hardware is configured with SG90,
+ * @param[in] channel
+ * @param[in] duty_cycle_ms
+ * @return 0 on success, otherwise a negative error value
+ */
+int resource_set_servo_motor_sg90_value(int channel, double duty_cycle_ms);
+
+/**
+ * This module is sample codes to handling Servo motors in Tizen platform.
+ * Hardware is configured with SG90,
+ * @param[in] channel
+ * @param[in] percent
+ * @return 0 on success, otherwise a negative error value
+ */
+int resource_rotate_servo_motor_by_percent(int channel, double percent);
+
+#endif /* __RESOURCE_SERVO_MOTOR_SG90_H__ */
--- /dev/null
+ /*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ *
+ * 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 __SERVO_H_H__
+#define __SERVO_H_H__
+
+#include "servo-type.h"
+
+int servo_h_initialize(void);
+int servo_h_finalize(void);
+int servo_h_state_set(double value, const char *pass_key);
+int servo_h_state_get(double *value);
+int servo_h_state_changed_cb_set(
+ const char *callback_key, servo_state_changed_cb callback, void *cb_data);
+
+#endif /* __SERVO_H_H__ */
--- /dev/null
+ /*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ *
+ * 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 __SERVO_TYPE_H__
+#define __SERVO_TYPE_H__
+
+typedef void(*servo_state_changed_cb) (double value, void* user_data);
+
+#endif /* __SERVO_TYPE_H__ */
--- /dev/null
+ /*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ *
+ * 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 __SERVO_V_H__
+#define __SERVO_V_H__
+
+#include "servo-type.h"
+
+int servo_v_initialize(void);
+int servo_v_finalize(void);
+int servo_v_state_set(double value, const char *pass_key);
+int servo_v_state_get(double *value);
+int servo_v_state_changed_cb_set(
+ const char *callback_key, servo_state_changed_cb callback, void *cb_data);
+
+#endif /* __SERVO_V_H__ */
--- /dev/null
+ /*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ *
+ * 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 __SAMSUNG_EXPERIENCE_SERVICE_SMARTTHINGS_H__
+#define __SAMSUNG_EXPERIENCE_SERVICE_SMARTTHINGS_H__
+
+#include <stdlib.h>
+#include <stdbool.h>
+#include <tizen.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @addtogroup CAPI_SMARTTHINGS_THING_MASTER_MODULE
+ * @{
+ */
+
+/**
+ * @brief Definition for the max length of SSID for access point.
+ * @since_ses 1
+ */
+#define SMARTTHINGS_SSID_LEN_MAX 32
+
+/**
+ * @brief Definition for the max length of cloud information.
+ * @since_ses 1
+ */
+#define SMARTTHINGS_CLOUD_INFO_LEN_MAX 128
+
+/**
+ * @brief Enumeration for the SmartThings error.
+ * @since_ses 1
+ */
+typedef enum {
+ SMARTTHINGS_ERROR_NONE = TIZEN_ERROR_NONE, /**< Successful */
+ SMARTTHINGS_ERROR_INVALID_PARAMETER = TIZEN_ERROR_INVALID_PARAMETER, /**< Invalid parameter */
+ SMARTTHINGS_ERROR_OUT_OF_MEMORY = TIZEN_ERROR_OUT_OF_MEMORY, /**< Out of memory */
+ SMARTTHINGS_ERROR_PERMISSION_DENIED = TIZEN_ERROR_PERMISSION_DENIED, /**< Permission denied */
+ SMARTTHINGS_ERROR_NO_DATA = TIZEN_ERROR_NO_DATA, /**< No data */
+ SMARTTHINGS_ERROR_NOT_SUPPORTED = TIZEN_ERROR_NOT_SUPPORTED, /**< Not supported */
+ SMARTTHINGS_ERROR_OPERATION_FAILED = TIZEN_ERROR_UNKNOWN - 1, /**< Operation failed */
+ SMARTTHINGS_ERROR_SERVICE_UNAVAILABLE = TIZEN_ERROR_UNKNOWN -2 /**< Service unavailable */
+} smartthings_error_e;
+
+/**
+ * @brief Enumeration for SmartThings status.
+ * @since_ses 1
+ */
+typedef enum {
+ SMARTTHINGS_STATUS_NOT_READY = -1, /**< Service agent is not ready */
+ SMARTTHINGS_STATUS_INIT = 0, /**< Initial state of SmartThings Thing */
+ SMARTTHINGS_STATUS_ES_STARTED, /**< Easy-setup is started */
+ SMARTTHINGS_STATUS_ES_DONE, /**< Easy-setup is done */
+ SMARTTHINGS_STATUS_ES_FAILED_ON_OWNERSHIP_TRANSFER, /**< Easy-setup failed due to Ownership-Transfer failure */
+ SMARTTHINGS_STATUS_CONNECTING_TO_AP, /**< Connecting to target Wi-Fi access point */
+ SMARTTHINGS_STATUS_CONNECTED_TO_AP, /**< Connected to target Wi-Fi access point */
+ SMARTTHINGS_STATUS_CONNECTING_TO_AP_FAILED, /**< Failed to connect to target Wi-Fi access point */
+ SMARTTHINGS_STATUS_REGISTERING_TO_CLOUD, /**< Trying to sign up, sign in and publish resources to cloud */
+ SMARTTHINGS_STATUS_REGISTERED_TO_CLOUD, /**< Publish resources to cloud is complete. Now the thing is ready to be controlled via cloud */
+ SMARTTHINGS_STATUS_REGISTERING_FAILED_ON_SIGN_IN, /**< Failed to sign in to cloud */
+ SMARTTHINGS_STATUS_REGISTERING_FAILED_ON_PUB_RES /**< Failed to publish resources to cloud */
+} smartthings_status_e;
+
+/**
+ * @brief Enumeration for RPC connection status.
+ * @since_ses 1
+ */
+typedef enum {
+ SMARTTHINGS_CONNECTION_STATUS_CONNECTED = 0, /**< Connection is connected */
+ SMARTTHINGS_CONNECTION_STATUS_DISCONNECTED, /**< Connection is disconnected */
+ SMARTTHINGS_CONNECTION_STATUS_REJECTED, /**< Connection is rejected */
+} smartthings_connection_status_e;
+
+/**
+ * @brief The Wi-Fi mode.
+ * @since_ses 1
+ */
+typedef enum {
+ SMARTTHINGS_WIFI_MODE_11A = (1 << 0), /**< Wi-Fi 11A */
+ SMARTTHINGS_WIFI_MODE_11B = (1 << 1), /**< Wi-Fi 11B */
+ SMARTTHINGS_WIFI_MODE_11G = (1 << 2), /**< Wi-Fi 11G */
+ SMARTTHINGS_WIFI_MODE_11N = (1 << 3), /**< Wi-Fi 11N */
+ SMARTTHINGS_WIFI_MODE_11AC = (1 << 4) /**< Wi-Fi 11AC */
+} smartthings_wifi_mode_e;
+
+/**
+ * @brief The Wi-Fi frequency band.
+ * @since_ses 1
+ */
+typedef enum {
+ SMARTTHINGS_WIFI_FREQ_24G = (1 << 0), /**< Wi-Fi 2.4GHz */
+ SMARTTHINGS_WIFI_FREQ_5G = (1 << 1), /**< Wi-Fi 5GHz */
+} smartthings_wifi_freq_e;
+
+/**
+ * @brief The Wi-Fi authentication type of access point.
+ * @since_ses 1
+ */
+typedef enum {
+ SMARTTHINGS_WIFI_AUTHTYPE_NONE = 0, /**< No authentication */
+ SMARTTHINGS_WIFI_AUTHTYPE_WEP, /**< WEP */
+ SMARTTHINGS_WIFI_AUTHTYPE_WPA_PSK, /**< WPA-PSK */
+ SMARTTHINGS_WIFI_AUTHTYPE_WPA2_PSK /**< WPA2-PSK */
+} smartthings_wifi_authtype_e;
+
+/**
+ * @brief The Wi-Fi encryption type of access point.
+ * @since_ses 1
+ */
+typedef enum {
+ SMARTTHINGS_WIFI_ENCTYPE_NONE = 0, /**< No encryption */
+ SMARTTHINGS_WIFI_ENCTYPE_WEP_64, /**< WEP 64 */
+ SMARTTHINGS_WIFI_ENCTYPE_WEP_128, /**< WEP 128 */
+ SMARTTHINGS_WIFI_ENCTYPE_TKIP, /**< TKIP */
+ SMARTTHINGS_WIFI_ENCTYPE_AES, /**< AES */
+ SMARTTHINGS_WIFI_ENCTYPE_TKIP_AES /**< TKIP/AES */
+} smartthings_wifi_enctype_e;
+
+/**
+ * @brief The SmartThings handle.
+ * @since_ses 1
+ */
+typedef struct smartthings_s *smartthings_h;
+
+/**
+ * @brief The access point information handle.
+ * @since_ses 1
+ */
+typedef struct smartthings_ap_info_s *smartthings_ap_info_h;
+
+/**
+ * @brief The device provisioning information handle.
+ * @since_ses 1
+ */
+typedef struct smartthings_device_prov_info_s *smartthings_device_prov_info_h;
+
+/**
+ * @brief The cloud information handle for cloud sign-up.
+ * @since_ses 1
+ */
+typedef struct smartthings_cloud_info_s *smartthings_cloud_info_h;
+
+/**
+ * @brief The access point list handle.
+ * @since_ses 1
+ */
+typedef struct smartthings_ap_list_s *smartthings_ap_list_h;
+
+/**
+ * @brief Callback for status of connection to SmartThings Thing agent.
+ * @details The following error codes can be received: \n
+ #SMARTTHINGS_ERROR_NONE: Success \n
+ #SMARTTHINGS_ERROR_PERMISSION_DENIED: Permission denied \n
+ #SMARTTHINGS_ERROR_SERVICE_UNAVAILABLE: Service unavailable \n
+ * @since_ses 1
+ *
+ * @remarks The @a handle should not be released.
+ * @remarks The @a handle is the same object for which the callback was set/added.
+ * @remarks The @a handle will be released when smartthings_deinitialize() is called.
+ * @remarks When callback is called, user can see result as #smartthings_error_e enumeration value.
+ * @remarks When callback is called, user can see connection status as #smartthings_connection_status_e enumeration value.
+ *
+ * @param[in] result The result of connection operation
+ * @param[in] handle The SmartThings handle
+ * @param[in] status The status of connection
+ * @param[in] user_data The user data passed from the callback registration function
+ *
+ * @see smartthings_initialize()
+ */
+typedef void (*smartthings_connection_status_cb)(smartthings_error_e result, smartthings_h handle, smartthings_connection_status_e status, void *user_data);
+
+/**
+ * @brief Callback for SmartThings Thing status.
+ * @since_ses 1
+ *
+ * @remarks The @a handle should not be released.
+ * @remarks The @a handle is the same object for which the callback was set/added.
+ * @remarks The @a handle will be released when smartthings_deinitialize() is called.
+ * @remarks When callback is called, user can see SmartThings status as #smartthings_status_e enumeration value.
+ *
+ * @param[in] handle The SmartThings handle
+ * @param[in] status The status of SmartThings
+ * @param[in] user_data The user data passed from the callback registration function
+ *
+ * @see smartthings_set_status_changed_cb()
+ * @see smartthings_unset_status_changed_cb()
+ */
+typedef void (*smartthings_status_changed_cb)(smartthings_h handle, smartthings_status_e status, void *user_data);
+
+/**
+ * @brief Callback for getting user's input regarding mutual verification.
+ * @since_ses 1
+ *
+ * @remarks The @a handle should not be released.
+ * @remarks The @a handle is the same object for which the callback was set/added.
+ * @remarks The @a handle will be released when smartthings_deinitialize() is called.
+ * @remarks When callback is called, user can send a confirmation for mutual verification as true or false.
+ *
+ * @param[in] handle The SmartThings handle
+ * @param[in] user_data The user data passed from the callback registration function
+ *
+ * @see smartthings_set_user_confirm_cb()
+ * @see smartthings_unset_user_confirm_cb()
+ */
+typedef void (*smartthings_user_confirm_cb)(smartthings_h handle, void *user_data);
+
+/**
+ * @brief Callback for getting user's opinion regarding device reset.
+ * @since_ses 1
+ *
+ * @remarks The @a handle should not be released.
+ * @remarks The @a handle is the same object for which the callback was set/added.
+ * @remarks The @a handle will be released when smartthings_deinitialize() is called.
+ * @remarks When callback is called, user can sends a confirmation for reset as true or false.
+ *
+ * @param[in] handle The SmartThings handle
+ * @param[in] user_data The user data passed from the callback registration function
+ *
+ * @see smartthings_set_reset_confirm_cb()
+ * @see smartthings_unset_reset_confirm_cb()
+ */
+typedef void (*smartthings_reset_confirm_cb)(smartthings_h handle, void *user_data);
+
+/**
+ * @brief Callback for result of reset operation.
+ * @since_ses 1
+ *
+ * @remarks The @a handle should not be released.
+ * @remarks The @a handle is the same object for which the callback was set/added.
+ * @remarks The @a handle will be released when smartthings_deinitialize() is called.
+ * @remarks When callback is called, user can check reset operation succeeds or fails.
+ *
+ * @param[in] handle The SmartThings handle
+ * @param[in] result The result of reset
+ * @param[in] user_data The user data passed from the callback registration function
+ *
+ * @see smartthings_set_reset_result_cb()
+ * @see smartthings_unset_reset_result_cb()
+ */
+typedef void (*smartthings_reset_result_cb)(smartthings_h handle, bool result, void *user_data);
+
+/**
+ * @brief Callback for carrying the randomly generated PIN information.
+ * @since_ses 1
+ *
+ * @remarks The @a handle should not be released.
+ * @remarks The @a handle is the same object for which the callback was set/added.
+ * @remarks The @a handle will be released when smartthings_deinitialize() is called.
+ * @remarks The @a pin can be used only in the callback. To use outside, make a copy.
+ * @remarks When callback is called, user can see PIN value and length.
+ *
+ * @param[in] handle The SmartThings handle
+ * @param[in] pin The PIN data in string format
+ * @param[in] size The PIN length of @a pin
+ * @param[in] user_data The user data passed from the callback registration function
+ *
+ * @see smartthings_set_pin_cb()
+ * @see smartthings_unset_pin_cb()
+ */
+typedef void (*smartthings_pin_generated_cb)(smartthings_h handle, const char* pin, size_t size, void *user_data);
+
+/**
+ * @brief Callback for informing the application to close the PIN display.
+ * @since_ses 1
+ *
+ * @remarks The @a handle should not be released.
+ * @remarks The @a handle is the same object for which the callback was set/added.
+ * @remarks The @a handle will be released when smartthings_deinitialize() is called.
+ * @remarks When callback is called, user can know PIN based ownership transfer is finished.
+ *
+ * @param[in] handle The SmartThings handle
+ * @param[in] user_data The user data passed from the callback registration function
+ *
+ * @see smartthings_set_pin_cb()
+ * @see smartthings_unset_pin_cb()
+ */
+typedef void (*smartthings_pin_display_close_cb)(smartthings_h handle, void *user_data);
+
+/**
+ * @brief Callback for informing Wi-Fi AP information to connect.
+ * @since_ses 1
+ *
+ * @remarks The @a handle should not be released.
+ * @remarks The @a handle is the same object for which the callback was set/added.
+ * @remarks The @a handle will be released when smartthings_deinitialize() is called.
+ * @remarks The @a ap_info_h should not be released.
+ * @remarks The @a ap_info_h will be released when smartthings_unset_wifi_ap_provisioning_cb() is called.
+ * @remarks When callback is called, user can get Wi-Fi provisioning information.
+ *
+ * @param[in] handle The SmartThings handle
+ * @param[in] ap_info_h The AP information handle
+ * @param[in] user_data The user data passed from the callback registration function
+ *
+ * @see smartthings_set_wifi_ap_provisioning_cb()
+ * @see smartthings_unset_wifi_ap_provisioning_cb()
+ */
+typedef void (*smartthings_wifi_ap_provisioning_cb)(smartthings_h handle, smartthings_ap_info_h ap_info_h, void *user_data);
+
+/**
+ * @brief Callback for informing device provisioning information.
+ * @since_ses 1
+ *
+ * @remarks The @a handle should not be released.
+ * @remarks The @a handle is the same object for which the callback was set/added.
+ * @remarks The @a handle will be released when smartthings_deinitialize() is called.
+ * @remarks The @a dev_prov_h should not be released.
+ * @remarks The @a dev_prov_h will be released when smartthings_unset_device_provisioning_cb() is called.
+ * @remarks When callback is called, user can get device provisioning information.
+ *
+ * @param[in] handle The SmartThings handle
+ * @param[in] dev_prov_h The device provisioning information handle
+ * @param[in] user_data The user data passed from the callback registration function
+ *
+ * @see smartthings_set_device_provisioning_cb()
+ * @see smartthings_unset_device_provisioning_cb()
+ */
+typedef void (*smartthings_device_provisioning_cb)(smartthings_h handle, smartthings_device_prov_info_h dev_prov_h, void *user_data);
+
+/**
+ * @brief Callback for informing the scan AP list request.
+ * @since_ses 1
+ *
+ * @remarks The @a handle should not be released.
+ * @remarks The @a handle is the same object for which the callback was set/added.
+ * @remarks The @a handle will be released when smartthings_deinitialize() is called.
+ * @remarks When callback is called, user scans access points, sets AP list and sends it to agent.
+ *
+ * @param[in] handle The SmartThings handle
+ * @param[in] req_id The request ID
+ * @param[in] user_data The user data passed from the callback registration function
+ *
+ * @see smartthings_set_scan_ap_cb()
+ * @see smartthings_unset_scan_ap_cb()
+ */
+typedef void (*smartthings_scan_ap_cb)(smartthings_h handle, int req_id, void *user_data);
+
+/**
+ * @brief Callback for informing the stop soft AP request.
+ * @since_ses 1
+ *
+ * @remarks The @a handle should not be released.
+ * @remarks The @a handle is the same object for which the callback was set/added.
+ * @remarks The @a handle will be released when smartthings_deinitialize() is called.
+ * @remarks When callback is called, user stops soft AP.
+ *
+ * @param[in] handle The SmartThings handle
+ * @param[in] user_data The user data passed from the callback registration function
+ *
+ * @see smartthings_set_stop_soft_ap_cb()
+ * @see smartthings_unset_stop_soft_ap_cb()
+ */
+typedef void (*smartthings_stop_soft_ap_cb)(smartthings_h handle, void *user_data);
+
+/**
+ * @brief Creates a handle and connects to agent.
+ * @since_ses 1
+ * @privilege %http://com.samsung.tizen.smartthings-thing/appdefined/smartthings-thing.master \n
+ * %http://tizen.org/privilege/appmanager.launch \n
+ * %http://tizen.org/privilege/datasharing
+ *
+ * @remarks The @a handle must be released using smartthings_deinitialize().
+ * @remarks Ths function returns #SMARTTHINGS_ERROR_PERMISSION_DENIED\n
+ * if the application has no app-defined privilege for 'http://com.samsung.tizen.smartthings-thing/appdefined/smartthings-thing.master'.
+ *
+ * @param[out] handle The SmartThings handle to be newly created on success
+ * @param[in] connection_status_cb The RPC connection status callback to register
+ * @param[in] user_data The user data to be passed to the callback function
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SMARTTHINGS_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval #SMARTTHINGS_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #SMARTTHINGS_ERROR_OPERATION_FAILED Operation failed
+ * @retval #SMARTTHINGS_ERROR_NOT_SUPPORTED Not supported
+ * @retval #SMARTTHINGS_ERROR_SERVICE_UNAVAILABLE Service unavailable
+ *
+ * @see smartthings_deinitialize()
+ */
+int smartthings_initialize(smartthings_h *handle,
+ smartthings_connection_status_cb connection_status_cb,
+ void *user_data);
+
+/**
+ * @brief Deinitializes a handle and disconnects from the agent.
+ * @since_ses 1
+ *
+ * @param[in] handle The SmartThings handle
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SMARTTHINGS_ERROR_OPERATION_FAILED Operation failed
+ *
+ * @see smartthings_initialize()
+ */
+int smartthings_deinitialize(smartthings_h handle);
+
+/**
+ * @brief Starts SmartThings Thing operation.
+ * @since_ses 1
+ * @privilege %http://com.samsung.tizen.smartthings-thing/appdefined/smartthings-thing.master \n
+ * %http://tizen.org/privilege/appmanager.launch \n
+ * %http://tizen.org/privilege/datasharing
+ *
+ * @param[in] handle The SmartThings handle
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SMARTTHINGS_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #SMARTTHINGS_ERROR_OPERATION_FAILED Operation failed
+ * @retval #SMARTTHINGS_ERROR_SERVICE_UNAVAILABLE Service unavailable
+ *
+ * @see smartthings_stop()
+ */
+int smartthings_start(smartthings_h handle);
+
+/**
+ * @brief Stops SmartThings Thing operation.
+ * @since_ses 1
+ * @privilege %http://com.samsung.tizen.smartthings-thing/appdefined/smartthings-thing.master \n
+ * %http://tizen.org/privilege/appmanager.launch \n
+ * %http://tizen.org/privilege/datasharing
+ *
+ * @param[in] handle The SmartThings handle
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SMARTTHINGS_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #SMARTTHINGS_ERROR_OPERATION_FAILED Operation failed
+ * @retval #SMARTTHINGS_ERROR_SERVICE_UNAVAILABLE Service unavailable
+ *
+ * @see smartthings_start()
+ */
+int smartthings_stop(smartthings_h handle);
+
+/**
+ * @brief Sets thing status changed callback.
+ * @since_ses 1
+ * @privilege %http://com.samsung.tizen.smartthings-thing/appdefined/smartthings-thing.master \n
+ * %http://tizen.org/privilege/appmanager.launch \n
+ * %http://tizen.org/privilege/datasharing
+ *
+ * @remarks Only one callback function can be set with this function.
+ * @remarks If multiple callbacks are set, the last one is registered only.
+ * @remarks Callback is called when SmartThings status is changed.
+ * @remarks When callback is called, user can get SmartThings status as #smartthings_status_e enumeration value.
+ *
+ * @param[in] handle The SmartThings handle
+ * @param[in] status_cb The status changed callback to register
+ * @param[in] user_data The user data to be passed to the callback function
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SMARTTHINGS_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #SMARTTHINGS_ERROR_OPERATION_FAILED Operation failed
+ * @retval #SMARTTHINGS_ERROR_SERVICE_UNAVAILABLE Service unavailable
+ *
+ * @see smartthings_unset_status_changed_cb()
+ */
+int smartthings_set_status_changed_cb(smartthings_h handle,
+ smartthings_status_changed_cb status_cb,
+ void *user_data);
+
+/**
+ * @brief Unsets thing status changed callback.
+ * @since_ses 1
+ * @privilege %http://com.samsung.tizen.smartthings-thing/appdefined/smartthings-thing.master \n
+ * %http://tizen.org/privilege/appmanager.launch \n
+ * %http://tizen.org/privilege/datasharing
+ *
+ * @param[in] handle The SmartThings handle
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SMARTTHINGS_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #SMARTTHINGS_ERROR_OPERATION_FAILED Operation failed
+ * @retval #SMARTTHINGS_ERROR_SERVICE_UNAVAILABLE Service unavailable
+ *
+ * @see smartthings_set_status_changed_cb()
+ */
+int smartthings_unset_status_changed_cb(smartthings_h handle);
+
+/**
+ * @brief Sets test certificate files.
+ * @since_ses 1
+ * @privilege %http://com.samsung.tizen.smartthings-thing/appdefined/smartthings-thing.master \n
+ * %http://tizen.org/privilege/appmanager.launch \n
+ * %http://tizen.org/privilege/datasharing
+ *
+ * @remarks These files should be placed in 'res' directory of application.
+ * @remarks This function is needed only for using test certificate.
+ * @remarks This function can be used before smartthings_start()
+ *
+ * @param[in] handle The SmartThings handle
+ * @param[in] certificate The certificate file
+ * @param[in] private_key The private key file
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SMARTTHINGS_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #SMARTTHINGS_ERROR_OPERATION_FAILED Operation failed
+ * @retval #SMARTTHINGS_ERROR_SERVICE_UNAVAILABLE Service unavailable
+ */
+int smartthings_set_certificate_file(smartthings_h handle, const char *certificate, const char *private_key);
+
+/**
+ * @brief Sets device property for Easy-setup.
+ * @since_ses 1
+ *
+ * @remarks This function can be used before smartthings_start()
+ *
+ * @param[in] handle The SmartThings handle
+ * @param[in] dev_name The device name
+ * @param[in] wifi_mode The supported Wi-Fi mode (bit masked value for #smartthings_wifi_mode_e)
+ * @param[in] wifi_freq The supported Wi-Fi frequency (bit masked value for #smartthings_wifi_freq_e)
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_ERROR_INVALID_PARAMETER Invalid parameter
+ */
+int smartthings_set_device_property(smartthings_h handle, const char* dev_name, int wifi_mode, int wifi_freq);
+
+/**
+ * @brief Gets a device ID.
+ * @since_ses 1
+ * @privilege %http://com.samsung.tizen.smartthings-thing/appdefined/smartthings-thing.master \n
+ * %http://tizen.org/privilege/appmanager.launch \n
+ * %http://tizen.org/privilege/datasharing
+ *
+ * @remarks The @a device_id should be released using free().
+ *
+ * @param[in] handle The SmartThings handle
+ * @param[out] device_id The device ID
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SMARTTHINGS_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #SMARTTHINGS_ERROR_OPERATION_FAILED Operation failed
+ * @retval #SMARTTHINGS_ERROR_SERVICE_UNAVAILABLE Service unavailable
+ */
+int smartthings_get_device_id(smartthings_h handle, char **device_id);
+
+/**
+ * @brief Gets a Easy-setup status.
+ * @since_ses 1
+ * @privilege %http://com.samsung.tizen.smartthings-thing/appdefined/smartthings-thing.master \n
+ * %http://tizen.org/privilege/appmanager.launch \n
+ * %http://tizen.org/privilege/datasharing
+ *
+ * @param[in] handle The SmartThings handle
+ * @param[out] is_completed The status of Easy-setup whether it is completed or not
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SMARTTHINGS_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #SMARTTHINGS_ERROR_OPERATION_FAILED Operation failed
+ * @retval #SMARTTHINGS_ERROR_SERVICE_UNAVAILABLE Service unavailable
+ */
+int smartthings_get_easysetup_status(smartthings_h handle, bool *is_completed);
+
+/**
+ * @brief Starts Easy-setup mode.
+ *
+ * @details This function requests for turning on soft AP to SmartThings Thing agent.
+ * @since_ses 1
+ * @privilege %http://com.samsung.tizen.smartthings-thing/appdefined/smartthings-thing.master \n
+ * %http://tizen.org/privilege/appmanager.launch \n
+ * %http://tizen.org/privilege/datasharing \n
+ * %http://tizen.org/privilege/softap
+ *
+ * @param[in] handle The SmartThings handle
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SMARTTHINGS_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #SMARTTHINGS_ERROR_OPERATION_FAILED Operation failed
+ * @retval #SMARTTHINGS_ERROR_SERVICE_UNAVAILABLE Service unavailable
+ *
+ * @see smartthings_stop_easysetup()
+ */
+int smartthings_start_easysetup(smartthings_h handle);
+
+/**
+ * @brief Stops Easy-setup mode.
+ *
+ * @details This function requests for turning off soft AP to SmartThings Thing agent.
+ * @since_ses 1
+ * @privilege %http://com.samsung.tizen.smartthings-thing/appdefined/smartthings-thing.master \n
+ * %http://tizen.org/privilege/appmanager.launch \n
+ * %http://tizen.org/privilege/datasharing \n
+ * %http://tizen.org/privilege/softap
+ *
+ * @param[in] handle The SmartThings handle
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SMARTTHINGS_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #SMARTTHINGS_ERROR_OPERATION_FAILED Operation failed
+ * @retval #SMARTTHINGS_ERROR_SERVICE_UNAVAILABLE Service unavailable
+ *
+ * @see smartthings_start_easysetup()
+ */
+int smartthings_stop_easysetup(smartthings_h handle);
+
+/**
+ * @brief Sets callback for getting user confirmation for mutual verification based just work ownership transfer.
+ * @since_ses 1
+ * @privilege %http://com.samsung.tizen.smartthings-thing/appdefined/smartthings-thing.master \n
+ * %http://tizen.org/privilege/appmanager.launch \n
+ * %http://tizen.org/privilege/datasharing
+ *
+ * @remarks Only one callback function can be set with this function.
+ * @remarks If multiple callbacks are set, the last one is registered only.
+ * @remarks Callback is called when it needs user's confirm for mutual verification based just work ownership transfer.
+ * @remarks When callback is called, user can send a confirmation for mutual verification based just work ownership transfer as true or false.
+ *
+ * @param[in] handle The SmartThings handle
+ * @param[in] confirm_cb The user confirm callback to register
+ * @param[in] user_data The user data to be passed to the callback function
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SMARTTHINGS_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #SMARTTHINGS_ERROR_OPERATION_FAILED Operation failed
+ * @retval #SMARTTHINGS_ERROR_SERVICE_UNAVAILABLE Service unavailable
+ *
+ * @see smartthings_unset_user_confirm_cb()
+ */
+int smartthings_set_user_confirm_cb(smartthings_h handle,
+ smartthings_user_confirm_cb confirm_cb,
+ void *user_data);
+
+/**
+ * @brief Unsets user confirmation callback.
+ * @since_ses 1
+ * @privilege %http://com.samsung.tizen.smartthings-thing/appdefined/smartthings-thing.master \n
+ * %http://tizen.org/privilege/appmanager.launch \n
+ * %http://tizen.org/privilege/datasharing
+ *
+ * @param[in] handle The SmartThings handle
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SMARTTHINGS_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #SMARTTHINGS_ERROR_OPERATION_FAILED Operation failed
+ * @retval #SMARTTHINGS_ERROR_SERVICE_UNAVAILABLE Service unavailable
+ *
+ * @see smartthings_set_user_confirm_cb()
+ */
+int smartthings_unset_user_confirm_cb(smartthings_h handle);
+
+/**
+ * @brief Sets reset confirmation callback.
+ * @since_ses 1
+ * @privilege %http://com.samsung.tizen.smartthings-thing/appdefined/smartthings-thing.master \n
+ * %http://tizen.org/privilege/appmanager.launch \n
+ * %http://tizen.org/privilege/datasharing
+ *
+ * @remarks Only one callback function can be set with this function.
+ * @remarks If multiple callbacks are set, the last one is registered only.
+ * @remarks Callback is called when it needs user's confirm for reset.
+ * @remarks When callback is called, user can send a confirmation for reset as true or false.
+ *
+ * @param[in] handle The SmartThings handle
+ * @param[in] confirm_cb The reset confirm callback to register
+ * @param[in] user_data The user data to be passed to the callback function
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SMARTTHINGS_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #SMARTTHINGS_ERROR_OPERATION_FAILED Operation failed
+ * @retval #SMARTTHINGS_ERROR_SERVICE_UNAVAILABLE Service unavailable
+ *
+ * @see smartthings_unset_reset_confirm_cb()
+ */
+int smartthings_set_reset_confirm_cb(smartthings_h handle,
+ smartthings_reset_confirm_cb confirm_cb,
+ void *user_data);
+
+/**
+ * @brief Unsets reset confirmation callback.
+ * @since_ses 1
+ * @privilege %http://com.samsung.tizen.smartthings-thing/appdefined/smartthings-thing.master \n
+ * %http://tizen.org/privilege/appmanager.launch \n
+ * %http://tizen.org/privilege/datasharing
+ *
+ * @param[in] handle The SmartThings handle
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SMARTTHINGS_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #SMARTTHINGS_ERROR_OPERATION_FAILED Operation failed
+ * @retval #SMARTTHINGS_ERROR_SERVICE_UNAVAILABLE Service unavailable
+ *
+ * @see smartthings_set_reset_confirm_cb()
+ */
+int smartthings_unset_reset_confirm_cb(smartthings_h handle);
+
+/**
+ * @brief Sets reset result callback.
+ * @since_ses 1
+ * @privilege %http://com.samsung.tizen.smartthings-thing/appdefined/smartthings-thing.master \n
+ * %http://tizen.org/privilege/appmanager.launch \n
+ * %http://tizen.org/privilege/datasharing
+ *
+ * @remarks Only one callback function can be set with this function.
+ * @remarks If multiple callbacks are set, the last one is registered only.
+ * @remarks Callback is called when reset operation returns its result.
+ * @remarks When callback is called, user can check reset operation succeeds or fails.
+ *
+ * @param[in] handle The SmartThings handle
+ * @param[in] reset_result_cb The reset result callback to register
+ * @param[in] user_data The user data to be passed to the callback function
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SMARTTHINGS_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #SMARTTHINGS_ERROR_OPERATION_FAILED Operation failed
+ * @retval #SMARTTHINGS_ERROR_SERVICE_UNAVAILABLE Service unavailable
+ *
+ * @see smartthings_unset_reset_result_cb()
+ */
+int smartthings_set_reset_result_cb(smartthings_h handle,
+ smartthings_reset_result_cb reset_result_cb,
+ void *user_data);
+
+/**
+ * @brief Unsets reset result callback.
+ * @since_ses 1
+ * @privilege %http://com.samsung.tizen.smartthings-thing/appdefined/smartthings-thing.master \n
+ * %http://tizen.org/privilege/appmanager.launch \n
+ * %http://tizen.org/privilege/datasharing
+ *
+ * @param[in] handle The SmartThings handle
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SMARTTHINGS_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #SMARTTHINGS_ERROR_OPERATION_FAILED Operation failed
+ * @retval #SMARTTHINGS_ERROR_SERVICE_UNAVAILABLE Service unavailable
+ *
+ * @see smartthings_set_reset_result_cb()
+ */
+int smartthings_unset_reset_result_cb(smartthings_h handle);
+
+
+/**
+ * @brief Sets callback for getting randomly generated PIN for the PIN-based ownership transfer request.
+ * @since_ses 1
+ * @privilege %http://com.samsung.tizen.smartthings-thing/appdefined/smartthings-thing.master \n
+ * %http://tizen.org/privilege/appmanager.launch \n
+ * %http://tizen.org/privilege/datasharing
+ *
+ * @remarks Only one callback function can be set with this function.
+ * @remarks If multiple callbacks are set, the last one is registered only.
+ * @remarks @a generated_cb callback is called when PIN is generated.
+ * @remarks @a close_cb callback is called when PIN based ownership transfer is finished.
+ * @remarks When @a generated_cb callback is called, user can see PIN value and length.
+ * @remarks When @a close_cb callback is called, user can know PIN based ownership transfer is finished.
+ *
+ * @param[in] handle The SmartThings handle
+ * @param[in] generated_cb The PIN generation callback to register
+ * @param[in] close_cb The PIN display close callback to register
+ * @param[in] user_data The user data to be passed to the callback function
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SMARTTHINGS_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #SMARTTHINGS_ERROR_OPERATION_FAILED Operation failed
+ * @retval #SMARTTHINGS_ERROR_SERVICE_UNAVAILABLE Service unavailable
+ *
+ * @see smartthings_unset_pin_cb()
+ */
+int smartthings_set_pin_cb(smartthings_h handle,
+ smartthings_pin_generated_cb generated_cb,
+ smartthings_pin_display_close_cb close_cb,
+ void *user_data);
+
+/**
+ * @brief Unsets PIN callback.
+ * @since_ses 1
+ * @privilege %http://com.samsung.tizen.smartthings-thing/appdefined/smartthings-thing.master \n
+ * %http://tizen.org/privilege/appmanager.launch \n
+ * %http://tizen.org/privilege/datasharing
+ *
+ * @param[in] handle The SmartThings handle
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SMARTTHINGS_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #SMARTTHINGS_ERROR_OPERATION_FAILED Operation failed
+ * @retval #SMARTTHINGS_ERROR_SERVICE_UNAVAILABLE Service unavailable
+ *
+ * @see smartthings_set_pin_cb()
+ */
+int smartthings_unset_pin_cb(smartthings_h handle);
+
+/**
+ * @brief Sets callback for getting Wi-Fi AP information during Easy-setup.
+ * @since_ses 1
+ * @privilege %http://com.samsung.tizen.smartthings-thing/appdefined/smartthings-thing.master \n
+ * %http://tizen.org/privilege/appmanager.launch \n
+ * %http://tizen.org/privilege/datasharing
+ *
+ * @remarks Only one callback function can be set with this function.
+ * @remarks If multiple callbacks are set, the last one is registered only.
+ * @remarks Callback is called when Wi-Fi provisioning event occurs.
+ * @remarks When callback is called, user can get Wi-Fi provisioning information.
+ *
+ * @param[in] handle The SmartThings handle
+ * @param[in] wifi_ap_cb The Wi-Fi AP callback to register
+ * @param[in] user_data The user data to be passed to the callback function
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SMARTTHINGS_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #SMARTTHINGS_ERROR_OPERATION_FAILED Operation failed
+ * @retval #SMARTTHINGS_ERROR_SERVICE_UNAVAILABLE Service unavailable
+ *
+ * @see smartthings_unset_wifi_ap_provisioning_cb()
+ */
+int smartthings_set_wifi_ap_provisioning_cb(smartthings_h handle,
+ smartthings_wifi_ap_provisioning_cb wifi_ap_cb,
+ void *user_data);
+
+/**
+ * @brief Unsets callback for getting Wi-Fi AP information during Easy-setup.
+ * @since_ses 1
+ * @privilege %http://com.samsung.tizen.smartthings-thing/appdefined/smartthings-thing.master \n
+ * %http://tizen.org/privilege/appmanager.launch \n
+ * %http://tizen.org/privilege/datasharing
+ *
+ * @param[in] handle The SmartThings handle
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SMARTTHINGS_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #SMARTTHINGS_ERROR_OPERATION_FAILED Operation failed
+ * @retval #SMARTTHINGS_ERROR_SERVICE_UNAVAILABLE Service unavailable
+ *
+ * @see smartthings_set_wifi_ap_provisioning_cb()
+ */
+int smartthings_unset_wifi_ap_provisioning_cb(smartthings_h handle);
+
+/**
+ * @brief Sets callback for getting device provisioning information.
+ * @since_ses 1
+ * @privilege %http://com.samsung.tizen.smartthings-thing/appdefined/smartthings-thing.master \n
+ * %http://tizen.org/privilege/appmanager.launch \n
+ * %http://tizen.org/privilege/datasharing
+ *
+ * @remarks Only one callback function can be set with this function.
+ * @remarks If multiple callbacks are set, the last one is registered only.
+ * @remarks Callback is called when device provisioning event occurs.
+ * @remarks When callback is called, user can get device provisioning information.
+ *
+ * @param[in] handle The SmartThings handle
+ * @param[in] dev_prov_cb The device provisioning callback to register
+ * @param[in] user_data The user data to be passed to the callback function
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SMARTTHINGS_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #SMARTTHINGS_ERROR_OPERATION_FAILED Operation failed
+ * @retval #SMARTTHINGS_ERROR_SERVICE_UNAVAILABLE Service unavailable
+ *
+ * @see smartthings_unset_device_provisioning_cb()
+ */
+int smartthings_set_device_provisioning_cb(smartthings_h handle,
+ smartthings_device_provisioning_cb dev_prov_cb,
+ void *user_data);
+
+/**
+ * @brief Unsets callback for getting device provisioning information.
+ * @since_ses 1
+ * @privilege %http://com.samsung.tizen.smartthings-thing/appdefined/smartthings-thing.master \n
+ * %http://tizen.org/privilege/appmanager.launch \n
+ * %http://tizen.org/privilege/datasharing
+ *
+ * @param[in] handle The SmartThings handle
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SMARTTHINGS_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #SMARTTHINGS_ERROR_OPERATION_FAILED Operation failed
+ * @retval #SMARTTHINGS_ERROR_SERVICE_UNAVAILABLE Service unavailable
+ *
+ * @see smartthings_set_device_provisioning_cb()
+ */
+int smartthings_unset_device_provisioning_cb(smartthings_h handle);
+
+/**
+ * @brief Sets callback for informing the scan AP list request.
+ * @since_ses 1
+ * @privilege %http://com.samsung.tizen.smartthings-thing/appdefined/smartthings-thing.master \n
+ * %http://tizen.org/privilege/appmanager.launch \n
+ * %http://tizen.org/privilege/datasharing
+ *
+ * @remarks Only one callback function can be set with this function.
+ * @remarks If multiple callbacks are set, the last one is registered only.
+ * @remarks Callback is called when GET request for access point list.
+ * @remarks When callback is called, user scans access points, sets AP list and sends it to agent.
+ *
+ * @param[in] handle The SmartThings handle
+ * @param[in] scan_ap_cb The callback to register
+ * @param[in] user_data The user data to be passed to the callback function
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SMARTTHINGS_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #SMARTTHINGS_ERROR_OPERATION_FAILED Operation failed
+ * @retval #SMARTTHINGS_ERROR_SERVICE_UNAVAILABLE Service unavailable
+ *
+ * @see smartthings_unset_scan_ap_cb()
+ * @see smartthings_send_ap_list()
+ */
+int smartthings_set_scan_ap_cb(smartthings_h handle,
+ smartthings_scan_ap_cb scan_ap_cb,
+ void *user_data);
+
+/**
+ * @brief Unsets callback for informing the scan AP list request.
+ * @since_ses 1
+ * @privilege %http://com.samsung.tizen.smartthings-thing/appdefined/smartthings-thing.master \n
+ * %http://tizen.org/privilege/appmanager.launch \n
+ * %http://tizen.org/privilege/datasharing
+ *
+ * @param[in] handle The SmartThings handle
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SMARTTHINGS_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #SMARTTHINGS_ERROR_OPERATION_FAILED Operation failed
+ * @retval #SMARTTHINGS_ERROR_SERVICE_UNAVAILABLE Service unavailable
+ *
+ * @see smartthings_set_scan_ap_cb()
+ */
+int smartthings_unset_scan_ap_cb(smartthings_h handle);
+
+/**
+ * @brief Sets callback for informing the stop soft AP request.
+ * @since_ses 1
+ * @privilege %http://com.samsung.tizen.smartthings-thing/appdefined/smartthings-thing.master \n
+ * %http://tizen.org/privilege/appmanager.launch \n
+ * %http://tizen.org/privilege/datasharing
+ *
+ * @remarks Only one callback function can be set with this function.
+ * @remarks If multiple callbacks are set, the last one is registered only.
+ * @remarks Callback is called when POST request for stopping soft AP.
+ * @remarks When callback is called, user stops soft AP.
+ *
+ * @param[in] handle The SmartThings handle
+ * @param[in] stop_soft_ap_cb The callback to register
+ * @param[in] user_data The user data to be passed to the callback function
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SMARTTHINGS_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #SMARTTHINGS_ERROR_OPERATION_FAILED Operation failed
+ * @retval #SMARTTHINGS_ERROR_SERVICE_UNAVAILABLE Service unavailable
+ *
+ * @see smartthings_unset_stop_soft_ap_cb()
+ */
+int smartthings_set_stop_soft_ap_cb(smartthings_h handle,
+ smartthings_stop_soft_ap_cb stop_soft_ap_cb,
+ void *user_data);
+
+/**
+ * @brief Unsets callback for informing the stop soft AP request.
+ * @since_ses 1
+ * @privilege %http://com.samsung.tizen.smartthings-thing/appdefined/smartthings-thing.master \n
+ * %http://tizen.org/privilege/appmanager.launch \n
+ * %http://tizen.org/privilege/datasharing
+ *
+ * @param[in] handle The SmartThings handle
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SMARTTHINGS_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #SMARTTHINGS_ERROR_OPERATION_FAILED Operation failed
+ * @retval #SMARTTHINGS_ERROR_SERVICE_UNAVAILABLE Service unavailable
+ *
+ * @see smartthings_set_stop_soft_ap_cb()
+ */
+int smartthings_unset_stop_soft_ap_cb(smartthings_h handle);
+
+/**
+ * @brief Sends a user confirmation for MUTUAL VERIFICATION BASED JUST WORK Ownership transfer.
+ * @since_ses 1
+ * @privilege %http://com.samsung.tizen.smartthings-thing/appdefined/smartthings-thing.master \n
+ * %http://tizen.org/privilege/appmanager.launch \n
+ * %http://tizen.org/privilege/datasharing \n
+ * %http://tizen.org/privilege/internet
+ *
+ * @param[in] handle The SmartThings handle
+ * @param[in] confirm The user confirmation for OTM(ownership transfer method)
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SMARTTHINGS_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #SMARTTHINGS_ERROR_OPERATION_FAILED Operation failed
+ * @retval #SMARTTHINGS_ERROR_SERVICE_UNAVAILABLE Service unavailable
+ *
+ * @see smartthings_set_user_confirm_cb()
+ * @see smartthings_unset_user_confirm_cb()
+ */
+int smartthings_send_user_confirm(smartthings_h handle, bool confirm);
+
+
+/**
+ * @brief Sends a reset confirmation.
+ * @since_ses 1
+ * @privilege %http://com.samsung.tizen.smartthings-thing/appdefined/smartthings-thing.master \n
+ * %http://tizen.org/privilege/appmanager.launch \n
+ * %http://tizen.org/privilege/datasharing \n
+ * %http://tizen.org/privilege/internet
+ *
+ * @param[in] handle The SmartThings handle
+ * @param[in] confirm The reset confirmation
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SMARTTHINGS_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #SMARTTHINGS_ERROR_OPERATION_FAILED Operation failed
+ * @retval #SMARTTHINGS_ERROR_SERVICE_UNAVAILABLE Service unavailable
+ *
+ * @see smartthings_set_reset_confirm_cb()
+ * @see smartthings_unset_reset_confirm_cb()
+ */
+int smartthings_send_reset_confirm(smartthings_h handle, bool confirm);
+
+/**
+ * @brief Sends a reset command for resetting the device's Cloud signup and Easy-setup.
+ * @since_ses 1
+ * @privilege %http://com.samsung.tizen.smartthings-thing/appdefined/smartthings-thing.master \n
+ * %http://tizen.org/privilege/appmanager.launch \n
+ * %http://tizen.org/privilege/datasharing \n
+ * %http://tizen.org/privilege/internet
+ *
+ * @param[in] handle The SmartThings handle
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SMARTTHINGS_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #SMARTTHINGS_ERROR_OPERATION_FAILED Operation failed
+ * @retval #SMARTTHINGS_ERROR_SERVICE_UNAVAILABLE Service unavailable
+ *
+ * @see smartthings_set_reset_result_cb()
+ * @see smartthings_unset_reset_result_cb()
+ */
+int smartthings_reset(smartthings_h handle);
+
+/**
+ * @brief Gets SSID of access point.
+ * @since_ses 1
+ *
+ * @remarks The @a ssid should be released using free().
+ *
+ * @param[in] ap_info_h The SmartThings AP information handle
+ * @param[out] ssid The SSID name
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SMARTTHINGS_ERROR_OPERATION_FAILED Operation failed
+ *
+ * @see smartthings_set_wifi_ap_provisioning_cb()
+ * @see smartthings_unset_wifi_ap_provisioning_cb()
+ */
+int smartthings_apinfo_get_ssid(smartthings_ap_info_h ap_info_h, char **ssid);
+
+/**
+ * @brief Gets password of access point.
+ * @since_ses 1
+ *
+ * @remarks The @a pwd should be released using free().
+ *
+ * @param[in] ap_info_h The SmartThings AP information handle
+ * @param[out] pwd The password
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SMARTTHINGS_ERROR_OPERATION_FAILED Operation failed
+ *
+ * @see smartthings_set_wifi_ap_provisioning_cb()
+ * @see smartthings_unset_wifi_ap_provisioning_cb()
+ */
+int smartthings_apinfo_get_password(smartthings_ap_info_h ap_info_h, char **pwd);
+
+/**
+ * @brief Gets authentification type of access point.
+ * @since_ses 1
+ *
+ * @param[in] ap_info_h The SmartThings AP information handle
+ * @param[out] authtype The authentification type
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SMARTTHINGS_ERROR_OPERATION_FAILED Operation failed
+ *
+ * @see smartthings_set_wifi_ap_provisioning_cb()
+ * @see smartthings_unset_wifi_ap_provisioning_cb()
+ */
+int smartthings_apinfo_get_authtype(smartthings_ap_info_h ap_info_h, smartthings_wifi_authtype_e *authtype);
+
+/**
+ * @brief Gets encryption type of access point.
+ * @since_ses 1
+ *
+ * @param[in] ap_info_h The SmartThings AP information handle
+ * @param[out] enctype The encryption type
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SMARTTHINGS_ERROR_OPERATION_FAILED Operation failed
+ *
+ * @see smartthings_set_wifi_ap_provisioning_cb()
+ * @see smartthings_unset_wifi_ap_provisioning_cb()
+ */
+int smartthings_apinfo_get_enctype(smartthings_ap_info_h ap_info_h, smartthings_wifi_enctype_e *enctype);
+
+/**
+ * @brief Gets channel information of access point.
+ * @since_ses 1
+ *
+ * @param[in] ap_info_h The SmartThings AP information handle
+ * @param[out] channel The frequency channel
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SMARTTHINGS_ERROR_OPERATION_FAILED Operation failed
+ *
+ * @see smartthings_set_wifi_ap_provisioning_cb()
+ * @see smartthings_unset_wifi_ap_provisioning_cb()
+ */
+int smartthings_apinfo_get_channel(smartthings_ap_info_h ap_info_h, int *channel);
+
+/**
+ * @brief Gets language of device provisioing information.
+ * @since_ses 1
+ *
+ * @remarks The @a language should be released using free().
+ *
+ * @param[in] dev_prov_h The SmartThings device provisioning information handle
+ * @param[out] language The IETF language tag using ISO 639X
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SMARTTHINGS_ERROR_OPERATION_FAILED Operation failed
+ *
+ * @see smartthings_set_device_provisioning_cb()
+ * @see smartthings_unset_device_provisioning_cb()
+ */
+int smartthings_devinfo_get_language(smartthings_device_prov_info_h dev_prov_h, char **language);
+
+/**
+ * @brief Gets country of device provisioing information.
+ * @since_ses 1
+ *
+ * @remarks The @a country should be released using free().
+ *
+ * @param[in] dev_prov_h The SmartThings device provisioning information handle
+ * @param[out] country The ISO Country Code (ISO 3166-1 Alpha-2)
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SMARTTHINGS_ERROR_OPERATION_FAILED Operation failed
+ *
+ * @see smartthings_set_device_provisioning_cb()
+ * @see smartthings_unset_device_provisioning_cb()
+ */
+int smartthings_devinfo_get_country(smartthings_device_prov_info_h dev_prov_h, char **country);
+
+/**
+ * @brief Gets datetime of device provisioing information.
+ * @since_ses 1
+ *
+ * @remarks The @a datetime should be released using free().
+ *
+ * @param[in] dev_prov_h The SmartThings device provisioning information handle
+ * @param[out] datetime The date and time
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SMARTTHINGS_ERROR_OPERATION_FAILED Operation failed
+ *
+ * @see smartthings_set_device_provisioning_cb()
+ * @see smartthings_unset_device_provisioning_cb()
+ */
+int smartthings_devinfo_get_datetime(smartthings_device_prov_info_h dev_prov_h, char **datetime);
+
+/**
+ * @brief Creates a SmartThings AP list handle.
+ * @since_ses 1
+ *
+ * @remarks The @a ap_list_h must be released using smartthings_aplist_destroy().
+ *
+ * @param[out] ap_list_h The SmartThings AP list handle to be newly created on success
+ * @param[in] count The count of AP
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SMARTTHINGS_ERROR_OUT_OF_MEMORY Out of memory
+ *
+ * @see smartthings_aplist_destroy()
+ */
+int smartthings_aplist_create(smartthings_ap_list_h *ap_list_h, unsigned int count);
+
+/**
+ * @brief Destroys a SmartThings AP list handle.
+ * @since_ses 1
+ *
+ * @param[in] ap_list_h The SmartThings AP list handle
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_ERROR_INVALID_PARAMETER Invalid parameter
+ *
+ * @see smartthings_aplist_create()
+ */
+int smartthings_aplist_destroy(smartthings_ap_list_h ap_list_h);
+
+/**
+ * @brief Sets SSID at the specific index of AP list handle.
+ * @since_ses 1
+ *
+ * @param[in] ap_list_h The SmartThings AP list handle
+ * @param[in] idx The index
+ * @param[in] ssid The SSID of AP
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_ERROR_INVALID_PARAMETER Invalid parameter
+ *
+ * @see smartthings_aplist_create()
+ * @see smartthings_aplist_destroy()
+ */
+int smartthings_aplist_set_ssid(smartthings_ap_list_h ap_list_h, int idx, const char *ssid);
+
+/**
+ * @brief Sets BSSID at the specific index of AP list handle.
+ * @since_ses 1
+ *
+ * @param[in] ap_list_h The SmartThings AP list handle
+ * @param[in] idx The index
+ * @param[in] bssid The BSSID of AP
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_ERROR_INVALID_PARAMETER Invalid parameter
+ *
+ * @see smartthings_aplist_create()
+ * @see smartthings_aplist_destroy()
+ */
+int smartthings_aplist_set_bssid(smartthings_ap_list_h ap_list_h, int idx, const char *bssid);
+
+/**
+ * @brief Sets authentification type at the specific index of AP list handle.
+ * @since_ses 1
+ *
+ * @param[in] ap_list_h The SmartThings AP list handle
+ * @param[in] idx The index
+ * @param[in] authtype The authentification type of AP
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_ERROR_INVALID_PARAMETER Invalid parameter
+ *
+ * @see smartthings_aplist_create()
+ * @see smartthings_aplist_destroy()
+ */
+int smartthings_aplist_set_authtype(smartthings_ap_list_h ap_list_h, int idx, smartthings_wifi_authtype_e authtype);
+
+/**
+ * @brief Sets encryption type at the specific index of AP list handle.
+ * @since_ses 1
+ *
+ * @param[in] ap_list_h The SmartThings AP list handle
+ * @param[in] idx The index
+ * @param[in] enctype The encryption type of AP
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_ERROR_INVALID_PARAMETER Invalid parameter
+ *
+ * @see smartthings_aplist_create()
+ * @see smartthings_aplist_destroy()
+ */
+int smartthings_aplist_set_enctype(smartthings_ap_list_h ap_list_h, int idx, smartthings_wifi_enctype_e enctype);
+
+/**
+ * @brief Sets frequency channel at the specific index of AP list handle.
+ * @since_ses 1
+ *
+ * @param[in] ap_list_h The SmartThings AP list handle
+ * @param[in] idx The index
+ * @param[in] channel The frequency channel of AP
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_ERROR_INVALID_PARAMETER Invalid parameter
+ *
+ * @see smartthings_aplist_create()
+ * @see smartthings_aplist_destroy()
+ */
+int smartthings_aplist_set_channel(smartthings_ap_list_h ap_list_h, int idx, int channel);
+
+/**
+ * @brief Sets signal level at the specific index of AP list handle.
+ * @since_ses 1
+ *
+ * @param[in] ap_list_h The SmartThings AP list handle
+ * @param[in] idx The index
+ * @param[in] signal_level The signal level of AP
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_ERROR_INVALID_PARAMETER Invalid parameter
+ *
+ * @see smartthings_aplist_create()
+ * @see smartthings_aplist_destroy()
+ */
+int smartthings_aplist_set_signal_level(smartthings_ap_list_h ap_list_h, int idx, int signal_level);
+
+/**
+ * @brief Sets max speed rate at the specific index of AP list handle.
+ * @since_ses 1
+ *
+ * @param[in] ap_list_h The SmartThings AP list handle
+ * @param[in] idx The index
+ * @param[in] max_rate The max speed rate of AP
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_ERROR_INVALID_PARAMETER Invalid parameter
+ *
+ * @see smartthings_aplist_create()
+ * @see smartthings_aplist_destroy()
+ */
+int smartthings_aplist_set_max_rate(smartthings_ap_list_h ap_list_h, int idx, int max_rate);
+
+/**
+ * @brief Sends the scanned AP list.
+ * @since_ses 1
+ * @privilege %http://com.samsung.tizen.smartthings-thing/appdefined/smartthings-thing.master \n
+ * %http://tizen.org/privilege/appmanager.launch \n
+ * %http://tizen.org/privilege/datasharing \n
+ * %http://tizen.org/privilege/internet
+ *
+ * @param[in] handle The SmartThings handle
+ * @param[in] ap_list_h The SmartThings AP list handle
+ * @param[in] req_id The request ID
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SMARTTHINGS_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval #SMARTTHINGS_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #SMARTTHINGS_ERROR_OPERATION_FAILED Operation failed
+ * @retval #SMARTTHINGS_ERROR_SERVICE_UNAVAILABLE Service unavailable
+ *
+ * @see smartthings_aplist_create()
+ * @see smartthings_aplist_destroy()
+ * @see smartthings_set_scan_ap_cb()
+ */
+int smartthings_send_ap_list(smartthings_h handle, smartthings_ap_list_h ap_list_h, int req_id);
+
+/**
+ * @brief Creates a SmartThings cloud information handle.
+ * @since_ses 1
+ *
+ * @remarks The @a cloud_info_h must be released using smartthings_cloudinfo_destroy().
+ *
+ * @param[out] cloud_info_h The SmartThings cloud information handle to be newly created on success
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SMARTTHINGS_ERROR_OUT_OF_MEMORY Out of memory
+ *
+ * @see smartthings_cloudinfo_destroy()
+ */
+int smartthings_cloudinfo_create(smartthings_cloud_info_h *cloud_info_h);
+
+/**
+ * @brief Destroys a SmartThings cloud information handle.
+ * @since_ses 1
+ *
+ * @param[in] cloud_info_h The SmartThings cloud information handle
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_ERROR_INVALID_PARAMETER Invalid parameter
+ *
+ * @see smartthings_cloudinfo_create()
+ */
+int smartthings_cloudinfo_destroy(smartthings_cloud_info_h cloud_info_h);
+
+/**
+ * @brief Sets region of cloud information.
+ * @since_ses 1
+ *
+ * @remarks The @a region can be set to one of "global" or "china".
+ * @remarks If it doesn't use this function, the @a region will be set to "global" internally.
+ *
+ * @param[in] cloud_info_h The SmartThings cloud information handle
+ * @param[in] region The region name
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_ERROR_INVALID_PARAMETER Invalid parameter
+ */
+int smartthings_cloudinfo_set_region(smartthings_cloud_info_h cloud_info_h, const char *region);
+
+/**
+ * @brief Sets authentification provider of cloud information.
+ * @since_ses 1
+ *
+ * @param[in] cloud_info_h The SmartThings cloud information handle
+ * @param[in] auth_provider The authentification provider
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_ERROR_INVALID_PARAMETER Invalid parameter
+ */
+int smartthings_cloudinfo_set_auth_provider(smartthings_cloud_info_h cloud_info_h, const char *auth_provider);
+
+/**
+ * @brief Sets access token of cloud information.
+ * @since_ses 1
+ *
+ * @param[in] cloud_info_h The SmartThings cloud information handle
+ * @param[in] access_token The access token
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_ERROR_INVALID_PARAMETER Invalid parameter
+ */
+int smartthings_cloudinfo_set_access_token(smartthings_cloud_info_h cloud_info_h, const char *access_token);
+
+/**
+ * @brief Sets refresh token of cloud information.
+ * @since_ses 1
+ *
+ * @param[in] cloud_info_h The SmartThings cloud information handle
+ * @param[in] refresh_token The refresh token
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_ERROR_INVALID_PARAMETER Invalid parameter
+ */
+int smartthings_cloudinfo_set_refresh_token(smartthings_cloud_info_h cloud_info_h, const char *refresh_token);
+
+/**
+ * @brief Sets user ID of cloud information.
+ * @since_ses 1
+ *
+ * @param[in] cloud_info_h The SmartThings cloud information handle
+ * @param[in] user_id The user ID
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_ERROR_INVALID_PARAMETER Invalid parameter
+ */
+int smartthings_cloudinfo_set_user_id(smartthings_cloud_info_h cloud_info_h, const char *user_id);
+
+/**
+ * @brief Sets client ID of cloud information.
+ * @since_ses 1
+ *
+ * @param[in] cloud_info_h The SmartThings cloud information handle
+ * @param[in] client_id The client ID
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_ERROR_INVALID_PARAMETER Invalid parameter
+ */
+int smartthings_cloudinfo_set_client_id(smartthings_cloud_info_h cloud_info_h, const char *client_id);
+
+/**
+ * @brief Requests to sign up to cloud.
+ * @since_ses 1
+ * @privilege %http://com.samsung.tizen.smartthings-thing/appdefined/smartthings-thing.master \n
+ * %http://tizen.org/privilege/appmanager.launch \n
+ * %http://tizen.org/privilege/datasharing \n
+ * %http://tizen.org/privilege/internet
+ *
+ * @param[in] handle The SmartThings handle
+ * @param[in] cloud_info_h The handle for cloud signup
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SMARTTHINGS_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #SMARTTHINGS_ERROR_OPERATION_FAILED Operation failed
+ * @retval #SMARTTHINGS_ERROR_SERVICE_UNAVAILABLE Service unavailable
+ */
+int smartthings_sign_up_cloud(smartthings_h handle, smartthings_cloud_info_h cloud_info_h);
+
+/**
+ * @brief Sets preconfigured PIN.
+ * @since_ses 1
+ * @privilege %http://com.samsung.tizen.smartthings-thing/appdefined/smartthings-thing.master \n
+ * %http://tizen.org/privilege/appmanager.launch \n
+ * %http://tizen.org/privilege/datasharing
+ *
+ * @param[in] handle The SmartThings handle
+ * @param[in] pin The PIN code to preconfigure
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SMARTTHINGS_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #SMARTTHINGS_ERROR_OPERATION_FAILED Operation failed
+ * @retval #SMARTTHINGS_ERROR_SERVICE_UNAVAILABLE Service unavailable
+ */
+int smartthings_set_preconfigured_pin(smartthings_h handle, const char* pin);
+
+/**
+ * @brief Sets MOT(multiple ownership transfer) status.
+ * @since_ses 1
+ * @privilege %http://com.samsung.tizen.smartthings-thing/appdefined/smartthings-thing.master \n
+ * %http://tizen.org/privilege/appmanager.launch \n
+ * %http://tizen.org/privilege/datasharing
+ *
+ * @param[in] handle The SmartThings handle
+ * @param[in] enable The MOT(multiple ownership transfer) status
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SMARTTHINGS_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #SMARTTHINGS_ERROR_OPERATION_FAILED Operation failed
+ * @retval #SMARTTHINGS_ERROR_SERVICE_UNAVAILABLE Service unavailable
+ */
+int smartthings_set_mot_status(smartthings_h handle, bool enable);
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __SAMSUNG_EXPERIENCE_SERVICE_SMARTTHINGS_H__ */
--- /dev/null
+ /*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ *
+ * 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 __SAMSUNG_EXPERIENCE_SERVICE_SMARTTHINGS_NOTIFICATION_H__
+#define __SAMSUNG_EXPERIENCE_SERVICE_SMARTTHINGS_NOTIFICATION_H__
+
+#include <smartthings_resource.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @file smartthings_notification.h
+ */
+
+/**
+ * @addtogroup CAPI_SMARTTHINGS_THING_NOTIFICATION_MODULE
+ * @{
+ */
+
+/**
+ * @brief Enumeration for the type of notification.
+ * @since_ses 1
+ */
+typedef enum {
+ SMARTTHINGS_NOTIFICATION_TYPE_ALERT = 1, /**< Alert type */
+ SMARTTHINGS_NOTIFICATION_TYPE_NOTICE, /**< Notice type */
+ SMARTTHINGS_NOTIFICATION_TYPE_EVENT, /**< Event type */
+ SMARTTHINGS_NOTIFICATION_TYPE_INFO, /**< Info type */
+ SMARTTHINGS_NOTIFICATION_TYPE_WARNING /**< Warning type */
+} smartthings_notification_type_e;
+
+
+/**
+ * @brief The SmartThings push message handle.
+ * @since_ses 1
+ */
+typedef struct smartthings_push_msg_s* smartthings_push_msg_h;
+
+/**
+ * @brief Creates a SmartThings push message handle.
+ * @since_ses 1
+ *
+ * @remarks The @a handle must be released using smartthings_push_msg_destroy().
+ *
+ * @param[out] handle The SmartThings push message handle to be newly created on success
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_OPERATION_FAILED Operation failed
+ *
+ * @see smartthings_push_msg_destroy()
+ */
+int smartthings_push_msg_create(smartthings_push_msg_h *handle);
+
+/**
+ * @brief Destroys a SmartThings push message handle and releases all its resources.
+ * @since_ses 1
+ *
+ * @param[in] handle The SmartThings push message handle
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_INVALID_PARAMETER Invalid parameter
+ *
+ * @see smartthings_push_msg_create()
+ */
+int smartthings_push_msg_destroy(smartthings_push_msg_h handle);
+
+/**
+ * @brief Sets a URI for the push message.
+ * @since_ses 1
+ *
+ * @param[in] handle The SmartThings push message handle
+ * @param[in] uri The URI of push message to set
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_INVALID_PARAMETER Invalid parameter
+ *
+ */
+int smartthings_push_msg_set_uri(smartthings_push_msg_h handle, const char *uri);
+
+/**
+ * @brief Sets a type for the push message.
+ * @since_ses 1
+ *
+ * @param[in] handle The SmartThings push message handle
+ * @param[in] type The type of push message to set
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_INVALID_PARAMETER Invalid parameter
+ *
+ */
+int smartthings_push_msg_set_type(smartthings_push_msg_h handle, smartthings_notification_type_e type);
+
+/**
+ * @brief Sets a code for the push message.
+ * @since_ses 1
+ *
+ * @param[in] handle The SmartThings push message handle
+ * @param[in] code The code of push message to set
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_INVALID_PARAMETER Invalid parameter
+ *
+ */
+int smartthings_push_msg_set_code(smartthings_push_msg_h handle, const char *code);
+
+/**
+ * @brief Sets a payload for the push message.
+ * @since_ses 1
+ *
+ * @param[in] handle The SmartThings push message handle
+ * @param[in] payload The payload of push message to set
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_INVALID_PARAMETER Invalid parameter
+ *
+ */
+int smartthings_push_msg_set_payload(smartthings_push_msg_h handle, smartthings_payload_h payload);
+
+/**
+ * @brief Sends the push message.
+ * @since_ses 1
+ * @privilege %http://com.samsung.tizen.smartthings-thing/appdefined/smartthings-thing.resource \n
+ * %http://tizen.org/privilege/appmanager.launch \n
+ * %http://tizen.org/privilege/datasharing \n
+ * %http://tizen.org/privilege/internet
+ *
+ * @param[in] st_h The SmartThings resource handle
+ * @param[in] push_msg_h The SmartThings push message handle
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_OPERATION_FAILED Operation failed
+ */
+int smartthings_send_push_msg(smartthings_resource_h st_h, smartthings_push_msg_h push_msg_h);
+
+
+/**
+ * @brief The SmartThings notification message handle.
+ * @since_ses 1
+ */
+typedef struct smartthings_notification_msg_s* smartthings_notification_msg_h;
+
+
+/**
+ * @brief Creates a SmartThings notification message handle.
+ * @since_ses 1
+ *
+ * @remarks The @a handle must be released using smartthings_notification_msg_destroy().
+ *
+ * @param[out] handle The SmartThings notification message handle to be newly created on success
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_OPERATION_FAILED Operation failed
+ *
+ * @see smartthings_notification_msg_destroy()
+ */
+int smartthings_notification_msg_create(smartthings_notification_msg_h *handle);
+
+/**
+ * @brief Destroys a SmartThings notification message handle and releases all its resources.
+ * @since_ses 1
+ *
+ * @param[in] handle The SmartThings notification message handle
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_INVALID_PARAMETER Invalid parameter
+ *
+ * @see smartthings_notification_msg_create()
+ */
+int smartthings_notification_msg_destroy(smartthings_notification_msg_h handle);
+
+/**
+ * @brief Sets a URI for the notification message.
+ * @since_ses 1
+ *
+ * @param[in] handle The SmartThings notification message handle
+ * @param[in] uri The URI of notification message to set
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_INVALID_PARAMETER Invalid parameter
+ *
+ */
+int smartthings_notification_msg_set_uri(smartthings_notification_msg_h handle, const char *uri);
+
+/**
+ * @brief Sets a type for the notification message.
+ * @since_ses 1
+ *
+ * @param[in] handle The SmartThings notification message handle
+ * @param[in] type The type of notification message to set
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_INVALID_PARAMETER Invalid parameter
+ *
+ */
+int smartthings_notification_msg_set_type(smartthings_notification_msg_h handle, smartthings_notification_type_e type);
+
+/**
+ * @brief Sets a payload for the notification message.
+ * @since_ses 1
+ *
+ * @param[in] handle The SmartThings notification message handle
+ * @param[in] name The name of payload
+ * @param[in] payload The payload of notification message to set
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_INVALID_PARAMETER Invalid parameter
+ *
+ */
+int smartthings_notification_msg_set_payload(smartthings_notification_msg_h handle, const char *name, smartthings_payload_h payload);
+
+/**
+ * @brief Sends the notification message.
+ * @since_ses 1
+ * @privilege %http://com.samsung.tizen.smartthings-thing/appdefined/smartthings-thing.resource \n
+ * %http://tizen.org/privilege/appmanager.launch \n
+ * %http://tizen.org/privilege/datasharing \n
+ * %http://tizen.org/privilege/internet
+ *
+ * @param[in] st_h The SmartThings resource handle
+ * @param[in] notification_msg_h The SmartThings notification message handle
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_OPERATION_FAILED Operation failed
+ */
+int smartthings_send_notification_msg(smartthings_resource_h st_h, smartthings_notification_msg_h notification_msg_h);
+
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __SAMSUNG_EXPERIENCE_SERVICE_SMARTTHINGS_NOTIFICATION_H__ */
--- /dev/null
+ /*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ *
+ * 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 __SAMSUNG_EXPERIENCE_SERVICE_SMARTTHINGS_PAYLOAD_H__
+#define __SAMSUNG_EXPERIENCE_SERVICE_SMARTTHINGS_PAYLOAD_H__
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @file smartthings_payload.h
+ */
+
+/**
+ * @addtogroup CAPI_SMARTTHINGS_THING_PAYLOAD_MODULE
+ * @{
+ */
+
+/**
+ * @brief The SmartThings payload handle.
+ * @since_ses 1
+ */
+typedef struct smartthings_payload_s *smartthings_payload_h;
+
+/**
+ * @brief Creates a SmartThings payload handle.
+ * @since_ses 1
+ *
+ * @remarks The @a payload must be released using smartthings_payload_destroy().
+ * @remarks If the @a payload is set to parent payload as an object or object array
+ * using smartthings_payload_set_object() or smartthings_payload_set_object_array(),
+ * the @a payload must not be released.
+
+ * @param[out] payload The SmartThings payload handle to be newly created on success
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_OUT_OF_MEMORY Out of memory
+ *
+ * @see smartthings_payload_destroy()
+ */
+int smartthings_payload_create(smartthings_payload_h *payload);
+
+/**
+ * @brief Destroys a SmartThings payload handle and releases all its resources.
+ * @since_ses 1
+ *
+ * @remarks If the @a payload has child payload, its child payload will be released as well.
+ *
+ * @param[in] payload The SmartThings payload handle
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_INVALID_PARAMETER Invalid parameter
+ *
+ * @see smartthings_payload_create()
+ */
+int smartthings_payload_destroy(smartthings_payload_h payload);
+
+/**
+ * @brief Sets an integer value for the attribute name.
+ * @since_ses 1
+ *
+ * @remarks The @a attr_name is key value, one of several properties of the resource type.
+ * @remarks The function replaces any existing value for the given @a attr_name.
+ *
+ * @param[in] payload The SmartThings payload handle
+ * @param[in] attr_name The attribute name
+ * @param[in] value The value to set
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_INVALID_PARAMETER Invalid parameter
+ */
+int smartthings_payload_set_int(smartthings_payload_h payload, const char *attr_name, int value);
+
+/**
+ * @brief Sets a boolean value for the attribute name.
+ * @since_ses 1
+ *
+ * @remarks The @a attr_name is key value, one of several properties of the resource type.
+ * @remarks The function replaces any existing value for the given @a attr_name.
+ *
+ * @param[in] payload The SmartThings payload handle
+ * @param[in] attr_name The attribute name
+ * @param[in] value The value to set
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_INVALID_PARAMETER Invalid parameter
+ */
+int smartthings_payload_set_bool(smartthings_payload_h payload, const char *attr_name, bool value);
+
+/**
+ * @brief Sets a double value for the attribute name.
+ * @since_ses 1
+ *
+ * @remarks The @a attr_name is key value, one of several properties of the resource type.
+ * @remarks The function replaces any existing value for the given @a attr_name.
+ *
+ * @param[in] payload The SmartThings payload handle
+ * @param[in] attr_name The attribute name
+ * @param[in] value The value to set
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_INVALID_PARAMETER Invalid parameter
+ */
+int smartthings_payload_set_double(smartthings_payload_h payload, const char *attr_name, double value);
+
+/**
+ * @brief Sets a string value for the attribute name.
+ * @since_ses 1
+ *
+ * @remarks The @a attr_name is key value, one of several properties of the resource type.
+ * @remarks The function replaces any existing value for the given @a attr_name.
+ *
+ * @param[in] payload The SmartThings payload handle
+ * @param[in] attr_name The attribute name
+ * @param[in] value The value to set
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_INVALID_PARAMETER Invalid parameter
+ */
+int smartthings_payload_set_string(smartthings_payload_h payload, const char *attr_name, const char *value);
+
+/**
+ * @brief Sets a byte string value and length for the attribute name.
+ * @since_ses 1
+ *
+ * @remarks The @a attr_name is key value, one of several properties of the resource type.
+ * @remarks The function replaces any existing value for the given @a attr_name.
+ *
+ * @param[in] payload The SmartThings payload handle
+ * @param[in] attr_name The attribute name
+ * @param[in] value The value to set
+ * @param[in] length The size of value
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_OPERATION_FAILED Operation failed
+ */
+int smartthings_payload_set_byte_string(smartthings_payload_h payload, const char *attr_name, const char *value, unsigned int length);
+
+/**
+ * @brief Sets an object value for the attribute name.
+ * @since_ses 1
+ *
+ * @remarks The @a attr_name is key value, one of several properties of the resource type.
+ * @remarks The @a value is SmartThings payload handle.
+ * @remarks The function replaces any existing value for the given @a attr_name.
+ *
+ * @param[in] payload The SmartThings payload handle
+ * @param[in] attr_name The attribute name
+ * @param[in] value The value to set
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_INVALID_PARAMETER Invalid parameter
+ */
+int smartthings_payload_set_object(smartthings_payload_h payload, const char *attr_name, smartthings_payload_h value);
+
+/**
+ * @brief Sets an integer array for the attribute name.
+ * @since_ses 1
+ *
+ * @remarks The @a attr_name is key value, one of several properties of the resource type.
+ * @remarks The function replaces any existing array for the given @a attr_name.
+ *
+ * @param[in] payload The SmartThings payload handle
+ * @param[in] attr_name The attribute name
+ * @param[in] array The array associated with the given attribute name
+ * @param[in] length The length of @a array
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_INVALID_PARAMETER Invalid parameter
+ */
+int smartthings_payload_set_int_array(smartthings_payload_h payload, const char *attr_name, const int *array, unsigned int length);
+
+/**
+ * @brief Sets a boolean array for the attribute name.
+ * @since_ses 1
+ *
+ * @remarks The @a attr_name is key value, one of several properties of the resource type.
+ * @remarks The function replaces any existing array for the given @a attr_name.
+ *
+ * @param[in] payload The SmartThings payload handle
+ * @param[in] attr_name The attribute name
+ * @param[in] array The array associated with the given attribute name
+ * @param[in] length The length of @a array
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_INVALID_PARAMETER Invalid parameter
+ */
+int smartthings_payload_set_bool_array(smartthings_payload_h payload, const char *attr_name, const bool *array, unsigned int length);
+
+/**
+ * @brief Sets a double array for the attribute name.
+ * @since_ses 1
+ *
+ * @remarks The @a attr_name is key value, one of several properties of the resource type.
+ * @remarks The function replaces any existing array for the given @a attr_name.
+ *
+ * @param[in] payload The SmartThings payload handle
+ * @param[in] attr_name The attribute name
+ * @param[in] array The array associated with the given attribute name
+ * @param[in] length The length of @a array
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_INVALID_PARAMETER Invalid parameter
+ */
+int smartthings_payload_set_double_array(smartthings_payload_h payload, const char *attr_name, const double *array, unsigned int length);
+
+/**
+ * @brief Sets a string array for the attribute name.
+ * @since_ses 1
+ *
+ * @remarks The @a attr_name is key value, one of several properties of the resource type.
+ * @remarks The function replaces any existing array for the given @a attr_name.
+ *
+ * @param[in] payload The SmartThings payload handle
+ * @param[in] attr_name The attribute name
+ * @param[in] array The array associated with the given attribute name
+ * @param[in] length The length of @a array
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_INVALID_PARAMETER Invalid parameter
+ */
+int smartthings_payload_set_string_array(smartthings_payload_h payload, const char *attr_name, const char **array, unsigned int length);
+
+/**
+ * @brief Sets an object array for the attribute name.
+ * @since_ses 1
+ *
+ * @remarks The @a attr_name is key value, one of several properties of the resource type.
+ * @remarks The function replaces any existing array for the given @a attr_name.
+ *
+ * @param[in] payload The SmartThings payload handle
+ * @param[in] attr_name The attribute name
+ * @param[in] array The array associated with the given attribute name
+ * @param[in] length The length of @a array
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_OUT_OF_MEMORY Out of memory
+ */
+int smartthings_payload_set_object_array(smartthings_payload_h payload, const char *attr_name, smartthings_payload_h *array, unsigned int length);
+
+/**
+ * @brief Adds a payload for child resource of collection resource.
+ * @since_ses 1
+ *
+ * @remarks The @a resource_uri is key value, one of several child resources of the collection resource.
+ * @remarks The @a value is SmartThings payload handle.
+ * @remarks The function replaces any existing payload for the given @a resource_uri.
+ *
+ * @param[in] payload The SmartThings payload handle
+ * @param[in] resource_uri The resource URI of child resource
+ * @param[in] value The payload associated with the given resource URI
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_INVALID_PARAMETER Invalid parameter
+ */
+int smartthings_payload_add_collection_object(smartthings_payload_h payload, const char *resource_uri, smartthings_payload_h value);
+
+/**
+ * @brief Gets an integer value for the attribute name.
+ * @since_ses 1
+ *
+ * @remarks The @a attr_name is key value, one of several properties of the resource type.
+ *
+ * @param[in] payload The SmartThings payload handle
+ * @param[in] attr_name The attribute name
+ * @param[out] value The value associated with the given attribute name
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_NO_DATA No data
+ */
+int smartthings_payload_get_int(smartthings_payload_h payload, const char *attr_name, int *value);
+
+/**
+ * @brief Gets a boolean value for the attribute name.
+ * @since_ses 1
+ *
+ * @remarks The @a attr_name is key value, one of several properties of the resource type.
+ *
+ * @param[in] payload The SmartThings payload handle
+ * @param[in] attr_name The attribute name
+ * @param[out] value The value associated with the given attribute name
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_NO_DATA No data
+ */
+int smartthings_payload_get_bool(smartthings_payload_h payload, const char *attr_name, bool *value);
+
+/**
+ * @brief Gets a double value for the attribute name.
+ * @since_ses 1
+ *
+ * @remarks The @a attr_name is key value, one of several properties of the resource type.
+ *
+ * @param[in] payload The SmartThings payload handle
+ * @param[in] attr_name The attribute name
+ * @param[out] value The value associated with the given attribute name
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_NO_DATA No data
+ */
+int smartthings_payload_get_double(smartthings_payload_h payload, const char *attr_name, double *value);
+
+/**
+ * @brief Gets a string value for the attribute name.
+ * @since_ses 1
+ *
+ * @remarks The @a attr_name is key value, one of several properties of the resource type.
+ * @remarks The @a value should be released using free().
+ *
+ * @param[in] payload The SmartThings payload handle
+ * @param[in] attr_name The attribute name
+ * @param[out] value The value associated with the given attribute name
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_NO_DATA No data
+ */
+int smartthings_payload_get_string(smartthings_payload_h payload, const char *attr_name, char **value);
+
+/**
+ * @brief Gets a byte string value and length for the attribute name.
+ * @since_ses 1
+ *
+ * @remarks The @a attr_name is key value, one of several properties of the resource type.
+ * @remarks The @a value should be released using free().
+ *
+ * @param[in] payload The SmartThings payload handle
+ * @param[in] attr_name The attribute name
+ * @param[out] value The value associated with the given attribute name
+ * @param[out] length The size of value
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_NO_DATA No data
+ */
+int smartthings_payload_get_byte_string(smartthings_payload_h payload, const char *attr_name, char **value, unsigned int *length);
+
+/**
+ * @brief Gets an object value for the attribute name.
+ * @since_ses 1
+ *
+ * @remarks The @a attr_name is key value, one of several properties of the resource type.
+ * @remarks The @a value is SmartThings payload handle.
+ * @remarks The @a value must be released using smartthings_payload_release_object().
+ *
+ * @param[in] payload The SmartThings payload handle
+ * @param[in] attr_name The attribute name
+ * @param[out] value The value associated with the given attribute name
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_NO_DATA No data
+ */
+int smartthings_payload_get_object(smartthings_payload_h payload, const char *attr_name, smartthings_payload_h *value);
+
+/**
+ * @brief Gets an integer array for the attribute name.
+ * @since_ses 1
+ *
+ * @remarks The @a attr_name is key value, one of several properties of the resource type.
+ * @remarks The @a array must be released using smartthings_payload_release_int_array().
+ *
+ * @param[in] payload The SmartThings payload handle
+ * @param[in] attr_name The attribute name
+ * @param[out] array The array associated with the given attribute name
+ * @param[out] length The length of @a array
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_NO_DATA No data
+ *
+ * @see smartthings_payload_release_int_array()
+ */
+int smartthings_payload_get_int_array(smartthings_payload_h payload, const char *attr_name, int **array, unsigned int *length);
+
+/**
+ * @brief Gets a boolean array for the attribute name.
+ * @since_ses 1
+ *
+ * @remarks The @a attr_name is key value, one of several properties of the resource type.
+ * @remarks The @a array must be released using smartthings_payload_release_bool_array().
+ *
+ * @param[in] payload The SmartThings payload handle
+ * @param[in] attr_name The attribute name
+ * @param[out] array The array associated with the given attribute name
+ * @param[out] length The length of @a array
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_NO_DATA No data
+ *
+ * @see smartthings_payload_release_bool_array()
+ */
+int smartthings_payload_get_bool_array(smartthings_payload_h payload, const char *attr_name, bool **array, unsigned int *length);
+
+/**
+ * @brief Gets a double array for the attribute name.
+ * @since_ses 1
+ *
+ * @remarks The @a attr_name is key value, one of several properties of the resource type.
+ * @remarks The @a array must be released using smartthings_payload_release_double_array().
+ *
+ * @param[in] payload The SmartThings payload handle
+ * @param[in] attr_name The attribute name
+ * @param[out] array The array associated with the given attribute name
+ * @param[out] length The length of @a array
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_NO_DATA No data
+ *
+ * @see smartthings_payload_release_double_array()
+ */
+int smartthings_payload_get_double_array(smartthings_payload_h payload, const char *attr_name, double **array, unsigned int *length);
+
+/**
+ * @brief Gets a string array for the attribute name.
+ * @since_ses 1
+ *
+ * @remarks The @a attr_name is key value, one of several properties of the resource type.
+ * @remarks The @a array must be released using smartthings_payload_release_string_array().
+ *
+ * @param[in] payload The SmartThings payload handle
+ * @param[in] attr_name The attribute name
+ * @param[out] array The array associated with the given attribute name
+ * @param[out] length The length of @a array
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_NO_DATA No data
+ *
+ * @see smartthings_payload_release_string_array()
+ */
+int smartthings_payload_get_string_array(smartthings_payload_h payload, const char *attr_name, char ***array, unsigned int *length);
+
+/**
+ * @brief Gets an object array for the attribute name.
+ * @since_ses 1
+ *
+ * @remarks The @a attr_name is key value, one of several properties of the resource type.
+ * @remarks The @a array is a list of SmartThings payload handle.
+ * @remarks The @a array must be released using smartthings_payload_release_object_array().
+ *
+ * @param[in] payload The SmartThings payload handle
+ * @param[in] attr_name The attribute name
+ * @param[out] array The array associated with the given attribute name
+ * @param[out] length The length of @a array
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_NO_DATA No data
+ *
+ * @see smartthings_payload_release_object_array()
+ */
+int smartthings_payload_get_object_array(smartthings_payload_h payload, const char *attr_name, smartthings_payload_h **array, unsigned int *length);
+
+/**
+ * @brief Gets a payload for child resource of collection resource.
+ * @since_ses 1
+ *
+ * @remarks The @a resource_uri is key value, one of several child resources of the collection resource.
+ * @remarks The @a value is SmartThings payload handle.
+ * @remarks The @a value must be released using smartthings_payload_release_object().
+ *
+ * @param[in] payload The SmartThings payload handle
+ * @param[in] resource_uri The resource URI of child resource
+ * @param[out] value The payload associated with the given resource URI
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_NO_DATA No data
+ */
+int smartthings_payload_get_collection_object(smartthings_payload_h payload, const char *resource_uri, smartthings_payload_h *value);
+
+/**
+ * @brief Releases an integer array of the SmartThings payload.
+ * @since_ses 1
+ *
+ * @param[in] array The array to release
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_INVALID_PARAMETER Invalid parameter
+ *
+ * @see smartthings_payload_get_int_array()
+ */
+int smartthings_payload_release_int_array(int *array);
+
+/**
+ * @brief Releases a boolean array of the SmartThings payload.
+ * @since_ses 1
+ *
+ * @param[in] array The array to release
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_INVALID_PARAMETER Invalid parameter
+ *
+ * @see smartthings_payload_get_bool_array()
+ */
+int smartthings_payload_release_bool_array(bool *array);
+
+/**
+ * @brief Releases a double array of the SmartThings payload.
+ * @since_ses 1
+ *
+ * @param[in] array The array to release
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_INVALID_PARAMETER Invalid parameter
+ *
+ * @see smartthings_payload_get_double_array()
+ */
+int smartthings_payload_release_double_array(double *array);
+
+/**
+ * @brief Releases a string array of the SmartThings payload.
+ * @since_ses 1
+ *
+ * @param[in] array The array to release
+ * @param[in] length The length of @a array
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_INVALID_PARAMETER Invalid parameter
+ *
+ * @see smartthings_payload_get_string_array()
+ */
+int smartthings_payload_release_string_array(char **array, unsigned int length);
+
+/**
+ * @brief Releases an object array of the SmartThings payload.
+ * @since_ses 1
+ *
+ * @param[in] array The array to release
+ * @param[in] length The length of @a array
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_INVALID_PARAMETER Invalid parameter
+ *
+ * @see smartthings_payload_get_object_array()
+ */
+int smartthings_payload_release_object_array(smartthings_payload_h *array, unsigned int length);
+
+/**
+ * @brief Releases a SmartThings payload.
+ * @since_ses 1
+ *
+ * @remarks The function is different with smartthings_payload_destroy().
+ * @remarks The function releases only payload value that is obtained by smartthings_payload_get_object().
+ *
+ * @param[in] payload The payload to release
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_INVALID_PARAMETER Invalid parameter
+ *
+ * @see smartthings_payload_get_object()
+ */
+int smartthings_payload_release_object(smartthings_payload_h payload);
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __SAMSUNG_EXPERIENCE_SERVICE_SMARTTHINGS_PAYLOAD_H__ */
--- /dev/null
+ /*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ *
+ * 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 __SAMSUNG_EXPERIENCE_SERVICE_SMARTTHINGS_RESOURCE_H__
+#define __SAMSUNG_EXPERIENCE_SERVICE_SMARTTHINGS_RESOURCE_H__
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <tizen.h>
+#include <smartthings_payload.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @file smartthings_resource.h
+ */
+
+/**
+ * @addtogroup CAPI_SMARTTHINGS_THING_RESOURCE_MODULE
+ * @{
+ */
+
+/**
+ * @brief Enumeration for the SmartThings resource error.
+ * @since_ses 1
+ */
+typedef enum {
+ SMARTTHINGS_RESOURCE_ERROR_NONE = TIZEN_ERROR_NONE, /**< Successful */
+ SMARTTHINGS_RESOURCE_ERROR_INVALID_PARAMETER = TIZEN_ERROR_INVALID_PARAMETER, /**< Invalid parameter */
+ SMARTTHINGS_RESOURCE_ERROR_OUT_OF_MEMORY = TIZEN_ERROR_OUT_OF_MEMORY, /**< Out of memory */
+ SMARTTHINGS_RESOURCE_ERROR_PERMISSION_DENIED = TIZEN_ERROR_PERMISSION_DENIED, /**< Permission denied */
+ SMARTTHINGS_RESOURCE_ERROR_NO_DATA = TIZEN_ERROR_NO_DATA, /**< No data */
+ SMARTTHINGS_RESOURCE_ERROR_NOT_SUPPORTED = TIZEN_ERROR_NOT_SUPPORTED, /**< Not supported */
+ SMARTTHINGS_RESOURCE_ERROR_OPERATION_FAILED = TIZEN_ERROR_UNKNOWN - 1, /**< Operation failed */
+ SMARTTHINGS_RESOURCE_ERROR_SERVICE_UNAVAILABLE = TIZEN_ERROR_UNKNOWN -2 /**< Service unavailable */
+} smartthings_resource_error_e;
+
+/**
+ * @brief Enumeration for the request type of resource and collection resource.
+ * @since_ses 1
+ */
+typedef enum {
+ SMARTTHINGS_RESOURCE_REQUEST_GET = 0, /**< Get request type */
+ SMARTTHINGS_RESOURCE_REQUEST_SET = 1, /**< Set request type */
+ SMARTTHINGS_RESOURCE_REQUEST_COLLECTION_GET = 2, /**< Get request type for collection */
+ SMARTTHINGS_RESOURCE_REQUEST_COLLECTION_SET = 3 /**< Set request type for collection */
+} smartthings_resource_req_type_e;
+
+/**
+ * @brief Enumeration for RPC connection status.
+ * @since_ses 1
+ */
+typedef enum {
+ SMARTTHINGS_RESOURCE_CONNECTION_STATUS_CONNECTED = 0, /**< Connection is connected */
+ SMARTTHINGS_RESOURCE_CONNECTION_STATUS_DISCONNECTED, /**< Connection is disconnected */
+ SMARTTHINGS_RESOURCE_CONNECTION_STATUS_REJECTED, /**< Connection is rejected */
+} smartthings_resource_connection_status_e;
+
+/**
+ * @brief The SmartThings resource handle.
+ * @since_ses 1
+ */
+typedef struct smartthings_resource_s *smartthings_resource_h;
+
+/**
+ * @brief Callback for status of connection to SmartThings Thing agent.
+ * @details The following error codes can be received: \n
+ #SMARTTHINGS_RESOURCE_ERROR_NONE: Success \n
+ #SMARTTHINGS_RESOURCE_ERROR_PERMISSION_DENIED: Permission denied \n
+ #SMARTTHINGS_RESOURCE_ERROR_SERVICE_UNAVAILABLE: Service unavailable \n
+ * @since_ses 1
+ *
+ * @remarks The @a handle should not be released.
+ * @remarks The @a handle is the same object for which the callback was set/added.
+ * @remarks The @a handle will be released when smartthings_deinitialize() is called.
+ * @remarks When callback is called, user can see result as #smartthings_resource_error_e enumeration value.
+ * @remarks When callback is called, user can see connection status as #smartthings_connection_status_e enumeration value.
+ *
+ * @param[in] result The result of connection operation
+ * @param[in] handle The SmartThings handle
+ * @param[in] status The status of connection
+ * @param[in] user_data The user data passed from the callback registration function
+ *
+ * @see smartthings_resource_initialize()
+ */
+typedef void (*smartthings_resource_connection_status_cb)(smartthings_resource_error_e result, smartthings_resource_h handle, smartthings_resource_connection_status_e status, void *user_data);
+
+
+/**
+ * @brief Callback for handling request(GET/SET) messages.
+ * @since_ses 1
+ *
+ * @remarks The @a payload is NULL when @a req_type is #SMARTTHINGS_RESOURCE_REQUEST_GET.
+ * @remarks The @a payload can be used only in the callback. To use outside, make a copy.
+ * @remarks The @a st_h should not be released.
+ * @remarks The @a st_h is the same object for which the callback was set/added.
+ * @remarks The @a st_h will be released when smartthings_resource_deinitialize() is called.
+ * @remarks The @a payload should not be released.
+ * @remarks The @a uri can be used only in the callback. To use outside, make a copy.
+ *
+ * @param[in] st_h The SmartThings resource handle
+ * @param[in] req_id The request ID of request message
+ * @param[in] uri The resource URI
+ * @param[in] req_type The request type for request message
+ * @param[in] payload The payload for SET request message
+ * @param[in] user_data The user data passed from the callback registration function
+ *
+ * @see smartthings_resource_set_request_cb()
+ * @see smartthings_resource_unset_request_cb()
+ */
+typedef void (*smartthings_resource_request_cb)(smartthings_resource_h st_h, int req_id, const char *uri,
+ smartthings_resource_req_type_e req_type,
+ smartthings_payload_h payload, void *user_data);
+
+/**
+ * @brief Callback for status of resource registration to cloud.
+ * @since_ses 1
+ *
+ * @remarks This callback will be called when status of resource registration is changed.
+ * @remarks The @a st_h should not be released.
+ * @remarks The @a st_h is the same object for which the callback was set/added.
+ * @remarks The @a st_h will be released when smartthings_resource_deinitialize() is called.
+ * @remarks The @a is_registered will be true when resources are registered to cloud.
+ *
+ * @param[in] st_h The SmartThings resource handle
+ * @param[in] is_registered The status of resource registration to cloud
+ * @param[in] user_data The user data passed from the callback registration function
+ *
+ * @see smartthings_resource_set_cloud_registration_status_cb()
+ * @see smartthings_resource_unset_cloud_registration_status_cb()
+ */
+typedef void (*smartthings_resource_cloud_registration_status_cb)(smartthings_resource_h st_h, bool is_registered, void *user_data);
+
+
+/**
+ * @brief Initializes a resource handle and connects to agent.
+ * @since_ses 1
+ * @privilege %http://com.samsung.tizen.smartthings-thing/appdefined/smartthings-thing.resource \n
+ * %http://tizen.org/privilege/appmanager.launch \n
+ * %http://tizen.org/privilege/datasharing
+ *
+ * @remarks The @a st_h must be released using smartthings_resource_deinitialize().
+ * @remarks Ths function returns #SMARTTHINGS_RESOURCE_ERROR_PERMISSION_DENIED\n
+ * if the application has no app-defined privilege for 'http://com.samsung.tizen.smartthings-thing/appdefined/smartthings-thing.resource'.
+ *
+ * @param[out] st_h The SmartThings resource handle to be newly created on success
+ * @param[in] connection_status_cb The connection status callback to register
+ * @param[in] user_data The user data to be passed to the callback function
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_OPERATION_FAILED Operation failed
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_NOT_SUPPORTED Not supported
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_SERVICE_UNAVAILABLE Service unavailable
+ *
+ * @see smartthings_resource_deinitialize()
+ */
+int smartthings_resource_initialize(smartthings_resource_h *st_h,
+ smartthings_resource_connection_status_cb connection_status_cb,
+ void *user_data);
+
+/**
+ * @brief Deinitializes a resource handle and disconnects from the agent.
+ * @since_ses 1
+ *
+ * @param[in] st_h The SmartThings resource handle
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_INVALID_PARAMETER Invalid parameter
+ *
+ * @see smartthings_resource_initialize()
+ */
+int smartthings_resource_deinitialize(smartthings_resource_h st_h);
+
+/**
+ * @brief Sets resource request callback.
+ * @since_ses 1
+ * @privilege %http://com.samsung.tizen.smartthings-thing/appdefined/smartthings-thing.resource \n
+ * %http://tizen.org/privilege/appmanager.launch \n
+ * %http://tizen.org/privilege/datasharing
+ *
+ * @param[in] st_h The SmartThings resource handle
+ * @param[in] req_cb The request callback to register
+ * @param[in] user_data The user data to be passed to the callback function
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_OPERATION_FAILED Operation failed
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_SERVICE_UNAVAILABLE Service unavailable
+ *
+ * @see smartthings_resource_unset_request_cb()
+ */
+int smartthings_resource_set_request_cb(smartthings_resource_h st_h,
+ smartthings_resource_request_cb req_cb,
+ void *user_data);
+
+/**
+ * @brief Unsets resource request callback.
+ * @since_ses 1
+ * @privilege %http://com.samsung.tizen.smartthings-thing/appdefined/smartthings-thing.resource \n
+ * %http://tizen.org/privilege/appmanager.launch \n
+ * %http://tizen.org/privilege/datasharing
+ *
+ * @param[in] st_h The SmartThings resource handle
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_OPERATION_FAILED Operation failed
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_SERVICE_UNAVAILABLE Service unavailable
+ *
+ * @see smartthings_resource_set_request_cb()
+ */
+int smartthings_resource_unset_request_cb(smartthings_resource_h st_h);
+
+/**
+ * @brief Sends response for resource request message.
+ * @since_ses 1
+ * @privilege %http://com.samsung.tizen.smartthings-thing/appdefined/smartthings-thing.resource \n
+ * %http://tizen.org/privilege/appmanager.launch \n
+ * %http://tizen.org/privilege/datasharing \n
+ * %http://tizen.org/privilege/internet
+ *
+ * @param[in] st_h The SmartThings resource handle
+ * @param[in] req_id The request ID of request message
+ * @param[in] uri The resource URI
+ * @param[in] payload The payload of response message
+ * @param[in] result The result of response
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_OPERATION_FAILED Operation failed
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_SERVICE_UNAVAILABLE Service unavailable
+ */
+int smartthings_resource_send_response(smartthings_resource_h st_h, int req_id, const char *uri, smartthings_payload_h payload, bool result);
+
+/**
+ * @brief Notifies resource change.
+ * @since_ses 1
+ * @privilege %http://com.samsung.tizen.smartthings-thing/appdefined/smartthings-thing.resource \n
+ * %http://tizen.org/privilege/appmanager.launch \n
+ * %http://tizen.org/privilege/datasharing \n
+ * %http://tizen.org/privilege/internet
+ *
+ * @param[in] st_h The SmartThings resource handle
+ * @param[in] uri The resource URI
+ * @param[in] payload The payload of response message
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_OPERATION_FAILED Operation failed
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_SERVICE_UNAVAILABLE Service unavailable
+ */
+int smartthings_resource_notify(smartthings_resource_h st_h, const char *uri, smartthings_payload_h payload);
+
+/**
+ * @brief Gets resource URIs.
+ * @since_ses 1
+ * @privilege %http://com.samsung.tizen.smartthings-thing/appdefined/smartthings-thing.resource \n
+ * %http://tizen.org/privilege/appmanager.launch \n
+ * %http://tizen.org/privilege/datasharing
+ *
+ * @remarks The @a uris should be released using free().
+ *
+ * @param[in] st_h The SmartThings resource handle
+ * @param[out] count The resource count
+ * @param[out] uris The resource URI list
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_OPERATION_FAILED Operation failed
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_SERVICE_UNAVAILABLE Service unavailable
+ */
+int smartthings_resource_get_uris(smartthings_resource_h st_h, int *count, char ***uris);
+
+/**
+ * @brief Sets cloud registration callback.
+ * @since_ses 1
+ * @privilege %http://com.samsung.tizen.smartthings-thing/appdefined/smartthings-thing.resource \n
+ * %http://tizen.org/privilege/appmanager.launch \n
+ * %http://tizen.org/privilege/datasharing
+ *
+ * @param[in] st_h The SmartThings resource handle
+ * @param[in] reg_cb The callback to register
+ * @param[in] user_data The user data to be passed to the callback function
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_OPERATION_FAILED Operation failed
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_SERVICE_UNAVAILABLE Service unavailable
+ *
+ * @see smartthings_resource_unset_cloud_registration_status_cb()
+ */
+int smartthings_resource_set_cloud_registration_status_cb(smartthings_resource_h st_h,
+ smartthings_resource_cloud_registration_status_cb reg_cb,
+ void *user_data);
+
+/**
+ * @brief Unsets cloud registration callback.
+ * @since_ses 1
+ * @privilege %http://com.samsung.tizen.smartthings-thing/appdefined/smartthings-thing.resource \n
+ * %http://tizen.org/privilege/appmanager.launch \n
+ * %http://tizen.org/privilege/datasharing
+ *
+ * @param[in] st_h The SmartThings resource handle
+ *
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_NONE Successful
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_OPERATION_FAILED Operation failed
+ * @retval #SMARTTHINGS_RESOURCE_ERROR_SERVICE_UNAVAILABLE Service unavailable
+ *
+ * @see smartthings_resource_set_cloud_registration_status_cb()
+ */
+int smartthings_resource_unset_cloud_registration_status_cb(smartthings_resource_h st_h);
+
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __SAMSUNG_EXPERIENCE_SERVICE_SMARTTHINGS_RESOURCE_H__ */
--- /dev/null
+ /*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ *
+ * 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 __ST_THING_MASTER_H__
+#define __ST_THING_MASTER_H__
+
+int st_thing_master_init();
+int st_thing_master_fini();
+
+#endif /* __ST_THING_MASTER_H__ */
--- /dev/null
+ /*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ *
+ * 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 __ST_THING_RESOURCE__
+#define __ST_THING_RESOURCE__
+
+int st_thing_resource_init(void);
+int st_thing_resource_fini(void);
+
+#endif /* __ST_THING_RESOURCE__ */
--- /dev/null
+ /*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ *
+ * 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 __SWITCH_H__
+#define __SWITCH_H__
+
+typedef enum {
+ SWITCH_STATE_OFF,
+ SWITCH_STATE_ON
+} switch_state_e;
+
+typedef void(*switch_state_changed_cb) (switch_state_e state, void* user_data);
+
+int switch_initialize(void);
+int switch_finalize(void);
+int switch_state_set(switch_state_e state, const char *pass_key);
+int switch_state_get(switch_state_e *state);
+int switch_state_changed_cb_set(
+ const char *callback_key, switch_state_changed_cb callback, void *cb_data);
+
+#endif /* __SWITCH_H__ */
--- /dev/null
+sdb root on
+sdb shell 'mount -o remount,rw /'
+
+sdb shell 'app_launcher -t iot-vision-camera'
+
+sdb push ~/GBS-ROOT/local/BUILD-ROOTS/scratch.armv7l.0/home/abuild/rpmbuild/RPMS/armv7l/iot-vision-camera-0.0.1-1.armv7l.rpm /tmp
+sdb shell 'cd /tmp; rpm -ivh --force iot-vision-camera-0.0.1-1.armv7l.rpm'
+
+sdb shell 'app_launcher -s iot-vision-camera'
+
+sdb shell 'systemctl status iot-dashboard'
--- /dev/null
+<manifest>
+ <request>
+ <domain name="_" />
+ </request>
+</manifest>
+
--- /dev/null
+[Unit]
+Description=IoT Dashboard
+After=network.target
+
+[Service]
+Type=idle
+SmackProcessLabel=System
+WorkingDirectory=/opt/home/dashboard
+ExecStart=/usr/bin/iotjs server.js
+Restart=on-failure
+RestartSec=0
+NonBlocking=yes
+KillMode=process
+TimeoutStopSec=5
+
+[Install]
+WantedBy=multi-user.target
--- /dev/null
+Name: iot-vision-camera
+%define dashboard iot-dashboard
+Summary: IoT Vision Camera App
+Group: Applications/Core Applications
+Version: 0.0.1
+Release: 1
+License: Apache-2.0
+Provides: %{name} = %{version}-%{release}
+Source0: %{name}-%{version}.tar.gz
+Source1: %{dashboard}.service
+
+BuildRequires: cmake
+BuildRequires: hash-signer
+BuildRequires: pkgconfig(ecore)
+BuildRequires: pkgconfig(capi-appfw-service-application)
+BuildRequires: pkgconfig(capi-system-peripheral-io)
+BuildRequires: pkgconfig(libtzplatform-config)
+BuildRequires: pkgconfig(gio-2.0)
+BuildRequires: pkgconfig(glib-2.0)
+BuildRequires: pkgconfig(dlog)
+BuildRequires: pkgconfig(capi-media-camera)
+BuildRequires: pkgconfig(capi-media-vision)
+BuildRequires: pkgconfig(capi-media-image-util)
+BuildRequires: pkgconfig(rpc-port)
+BuildRequires: pkgconfig(libexif)
+BuildRequires: pkgconfig(capi-appfw-package-manager)
+
+%description
+IoT Vision Camera Application
+
+%prep
+%setup -q
+
+%build
+
+%ifarch %{arm}
+export CFLAGS="$CFLAGS -DTIZEN_BUILD_TARGET"
+export CXXFLAGS="$CXXFLAGS -DTIZEN_BUILD_TARGET"
+export FFLAGS="$FFLAGS -DTIZEN_BUILD_TARGET"
+%else
+export CFLAGS="$CFLAGS -DTIZEN_BUILD_EMULATOR"
+export CXXFLAGS="$CXXFLAGS -DTIZEN_BUILD_EMULATOR"
+export FFLAGS="$FFLAGS -DTIZEN_BUILD_EMULATOR"
+%endif
+
+%define _pkg_dir %{TZ_SYS_RO_APP}/%{name}
+%define _pkg_shared_dir %{_pkg_dir}/shared
+%define _pkg_res_dir %{_pkg_dir}/res
+%define _pkg_shared_res_dir %{_pkg_shared_dir}/res
+%define _sys_packages_dir %{TZ_SYS_RO_PACKAGES}
+%define _dashboard_dir /opt/home/
+
+cmake . -DP_NAME=%{name} \
+ -DINSTALL_PREFIX=%{_pkg_dir} \
+ -DAPP_SHARED_RES_DIR=%{_pkg_shared_res_dir} \
+ -DDASH_BOARD_DIR=%{_dashboard_dir} \
+ -DSYS_PACKAGES_DIR=%{_sys_packages_dir} \
+
+make %{?jobs:-j%jobs}
+
+%install
+%make_install
+
+mkdir -p %{buildroot}%{_unitdir}/multi-user.target.wants
+install -m 0644 %SOURCE1 %{buildroot}%{_unitdir}/%{dashboard}.service
+%install_service multi-user.target.wants %{dashboard}.service
+
+%define tizen_sign 1
+%define tizen_sign_base %{_pkg_dir}
+%define tizen_sign_level platform
+%define tizen_author_sign 1
+%define tizen_dist_sign 1
+
+%post
+/bin/systemctl stop %{dashboard}
+/bin/systemctl daemon-reload
+/bin/systemctl start %{dashboard}
+
+%postun
+/bin/systemctl stop %{dashboard}
+
+%files
+%manifest %{name}.manifest
+%license LICENSE NOTICE
+%defattr(-,root,root,-)
+%{_pkg_dir}/bin/%{name}
+%{_pkg_dir}/lib/*
+%{_pkg_dir}/author-signature.xml
+%{_pkg_dir}/signature1.xml
+%{_sys_packages_dir}/%{name}.xml
+%{_pkg_shared_res_dir}/*.png
+%{_pkg_res_dir}/*
+%{_pkg_shared_res_dir}/*.json
+%{_unitdir}/%{dashboard}.service
+%{_unitdir}/multi-user.target.wants/%{dashboard}.service
+%{_dashboard_dir}/*
--- /dev/null
+{
+ "devices": [
+ {
+ "deviceType": "oic.d.camera",
+ "deviceName": "YOUR-DEVICE-NAME",
+ "mnid": "YOUR-MNID",
+ "vid": "YOUR-VENDER-ID"
+ }
+ ],
+ "configuration": {
+ "otm": 2,
+ "otmDescription" : "ownershipTransferMethod : b0001(Random PIN-based), b0010(UserConfirm-based)",
+ "crtType" : 1,
+ "crtDescription" : "certificate type: 1(Test Certificate), 2(Artik Certificate)",
+ "easySetup": {
+ "mode": 1,
+ "modeDescription" : "easysetup mode : 1(SoftAP)",
+ "setupId": "YOUR-SETUP-ID"
+ }
+ }
+}
--- /dev/null
+{
+ "resources": {
+ "single": [
+ {
+ "uri": "/capability/switch/main/0",
+ "types": [
+ "x.com.st.powerswitch"
+ ],
+ "interfaces": [
+ "oic.if.a",
+ "oic.if.baseline"
+ ]
+ },
+ {
+ "uri": "/capability/motionSensor/main/0",
+ "types": [
+ "oic.r.sensor.motion"
+ ],
+ "interfaces": [
+ "oic.if.s",
+ "oic.if.baseline"
+ ]
+ },
+ {
+ "uri": "/capability/switchLevel/main/0",
+ "types": [
+ "oic.r.light.dimming"
+ ],
+ "interfaces": [
+ "oic.if.a",
+ "oic.if.baseline"
+ ]
+ },
+ {
+ "uri": "/capability/audioVolume/main/0",
+ "types": [
+ "x.com.st.audiovolume"
+ ],
+ "interfaces": [
+ "oic.if.a",
+ "oic.if.baseline"
+ ]
+ }
+ ]
+ },
+ "resourceTypes": [
+ {
+ "type": "x.com.st.powerswitch",
+ "properties": [
+ {
+ "key": "power",
+ "type": "string",
+ "mandatory": true,
+ "description": "State of the power switch.",
+ "enumDescription": ["on", "off"]
+ }
+ ]
+ },
+ {
+ "type": "oic.r.sensor.motion",
+ "properties": [
+ {
+ "key": "value",
+ "type": "boolean",
+ "mandatory": true,
+ "description": "motion detect"
+ }
+ ]
+ },
+ {
+ "type": "oic.r.light.dimming",
+ "properties": [
+ {
+ "key": "dimmingSetting",
+ "type": "integer",
+ "mandatory": true,
+ "description": "test dimming value."
+ }
+ ]
+ },
+ {
+ "type": "x.com.st.audiovolume",
+ "properties": [
+ {
+ "key": "volume",
+ "type": "integer",
+ "mandatory": true,
+ "description": "Volume setting of an audio rendering device."
+ },
+ {
+ "key": "mute",
+ "type": "boolean",
+ "mandatory": true,
+ "description": "Mute setting of an audio rendering device"
+ },
+ {
+ "key": "command",
+ "type": "string",
+ "description": "Comand for controlling",
+ "enumDescription": ["increase", "decrease", "max", "min"]
+ }
+ ]
+ }
+ ]
+}
--- /dev/null
+{
+ "name": "YOUR_DEVICE_NAME",
+ "components": [
+ {
+ "id": "main",
+ "capabilities": [
+ {
+ "id": "switch"
+ },
+ {
+ "id": "audioVolume"
+ },
+ {
+ "id": "motionSensor"
+ },
+ {
+ "id": "switchLevel"
+ }
+ ]
+ }
+ ],
+ "metadata": {
+ "mnmn": "",
+ "vid": "YOUR_VENDER_ID",
+ "deviceType": "Others"
+ }
+}
\ No newline at end of file
--- /dev/null
+{
+ "n": "YOUR_DEVICE_NAME",
+ "version": "0.0.1",
+ "vid": "",
+ "mnmn": "",
+ "language": [
+ {
+ "locale": "en_US",
+ "version": "0.0.1",
+ "poCodes": [
+ {
+ "po": "___PO_CODE_POWERSWITCH_ON",
+ "label": "On"
+ },
+ {
+ "po": "___PO_CODE_POWERSWITCH_OFF",
+ "label": "Off"
+ },
+ {
+ "po": "___PO_CODE_POWERSWITCH",
+ "label": "Power"
+ },
+ {
+ "label": "Command",
+ "po": "___PO_CODE_AUDIOVOLUME_COMMAND"
+ },
+ {
+ "label": "Increase",
+ "po": "___PO_CODE_AUDIOVOLUME_INCREASE"
+ },
+ {
+ "label": "Decrease",
+ "po": "___PO_CODE_AUDIOVOLUME_DECREASE"
+ },
+ {
+ "label": "Max",
+ "po": "___PO_CODE_AUDIOVOLUME_MAX"
+ },
+ {
+ "label": "Min",
+ "po": "___PO_CODE_AUDIOVOLUME_MIN"
+ },
+ {
+ "label": "Volume",
+ "po": "___PO_CODE_AUDIOVOLUME_VOLUME"
+ },
+ {
+ "label": "Mute",
+ "po": "___PO_CODE_AUDIOVOLUME_MUTE"
+ },
+ {
+ "label": "Unmute",
+ "po": "___PO_CODE_AUDIOVOLUME_UNMUTE"
+ },
+ {
+ "label": "Volume",
+ "po": "___PO_CODE_AUDIOVOLUME_MUTE_ACTION"
+ },
+ {
+ "label": "Motion sensor",
+ "po": "___PO_CODE_MOTIONSENSOR"
+ },
+ {
+ "label": "No motion",
+ "po": "___PO_CODE_MOTIONSENSOR_NO_MOTION"
+ },
+ {
+ "label": "Motion detected",
+ "po": "___PO_CODE_MOTIONSENSOR_MOTION_DETECTED"
+ },
+ {
+ "label": "Dimmer",
+ "po": "___PO_CODE_SWITCHLEVEL_DIMMING"
+ }
+ ],
+ "mnmn": "",
+ "vid": ""
+ }
+ ],
+ "ma": [
+ {
+ "name": "PowerSwitch",
+ "type": "main",
+ "order": 1,
+ "link": {
+ "href": "/capability/switch/main/0",
+ "if": "oic.if.a",
+ "rt": "x.com.st.powerswitch"
+ },
+ "iconUrl": {
+ "vector": "",
+ "small": "",
+ "large": "",
+ "mid": "icon://ic_function_power_switch"
+ },
+ "property": "power",
+ "controlType": "ToggleSwitch",
+ "alternatives": [
+ {
+ "key": "on",
+ "value": "___PO_CODE_POWERSWITCH_ON"
+ },
+ {
+ "key": "off",
+ "value": "___PO_CODE_POWERSWITCH_OFF",
+ "type": "inactive"
+ }
+ ],
+ "step": 0,
+ "label": {
+ "label": "___PO_CODE_POWERSWITCH"
+ },
+ "emphasis": false
+ }
+ ],
+ "ms": [
+ {
+ "name": "PowerSwitch",
+ "type": "device",
+ "order": 1,
+ "label": {
+ "label": "<var1>",
+ "arguments": [
+ {
+ "n": "var1",
+ "href": "/capability/switch/main/0",
+ "property": "power",
+ "valueType": null,
+ "alternatives": [
+ {
+ "key": "on",
+ "value": "___PO_CODE_POWERSWITCH_ON"
+ },
+ {
+ "key": "off",
+ "value": "___PO_CODE_POWERSWITCH_OFF",
+ "type": "inactive"
+ }
+ ]
+ }
+ ]
+ },
+ "emphasis": false
+ }
+ ],
+ "dpInfo": [
+ {
+ "os": "android",
+ "dpType": "vendorPlugIn",
+ "dpUri": "wwst://iot2018"
+ },
+ {
+ "os": "ios",
+ "dpType": "vendorPlugIn",
+ "dpUri": "wwst://iot2018"
+ }
+ ],
+ "dpResources": [
+ {
+ "name": "PowerSwitch",
+ "controllable": true,
+ "order": 1,
+ "link": {
+ "href": "/capability/switch/main/0",
+ "if": "oic.if.a",
+ "rt": "x.com.st.powerswitch"
+ },
+ "iconUrl": {
+ "vector": "",
+ "small": "",
+ "large": "",
+ "mid": "icon://ic_function_power_switch"
+ },
+ "property": "power",
+ "controlType": "ToggleSwitch",
+ "alternatives": [
+ {
+ "key": "on",
+ "value": "___PO_CODE_POWERSWITCH_ON"
+ },
+ {
+ "key": "off",
+ "value": "___PO_CODE_POWERSWITCH_OFF",
+ "type": "inactive"
+ }
+ ],
+ "step": 0,
+ "label": {
+ "label": "___PO_CODE_POWERSWITCH"
+ },
+ "emphasis": true,
+ "ruleEvent": false,
+ "ruleAction": true
+ },
+ {
+ "name": "PowerSwitch",
+ "controllable": true,
+ "order": 2,
+ "link": {
+ "href": "/capability/switch/main/0",
+ "if": "oic.if.a",
+ "rt": "x.com.st.powerswitch"
+ },
+ "iconUrl": {
+ "vector": "",
+ "small": "",
+ "large": "",
+ "mid": "icon://ic_function_power_switch"
+ },
+ "property": "power",
+ "controlType": "ToggleSwitch",
+ "alternatives": [
+ {
+ "key": "on",
+ "value": "___PO_CODE_POWERSWITCH_ON"
+ },
+ {
+ "key": "off",
+ "value": "___PO_CODE_POWERSWITCH_OFF",
+ "type": "inactive"
+ }
+ ],
+ "step": 0,
+ "label": {
+ "label": "___PO_CODE_POWERSWITCH"
+ },
+ "emphasis": true,
+ "ruleEvent": false,
+ "ruleAction": false
+ },
+ {
+ "name": "PowerSwitch",
+ "controllable": true,
+ "order": 3,
+ "link": {
+ "href": "/capability/switch/main/0",
+ "if": "oic.if.a",
+ "rt": "x.com.st.powerswitch"
+ },
+ "iconUrl": {
+ "vector": "",
+ "small": "",
+ "large": "",
+ "mid": "icon://ic_function_power_switch"
+ },
+ "property": "power",
+ "controlType": "ToggleSwitch",
+ "alternatives": [
+ {
+ "key": "on",
+ "value": "___PO_CODE_POWERSWITCH_ON"
+ },
+ {
+ "key": "off",
+ "value": "___PO_CODE_POWERSWITCH_OFF",
+ "type": "inactive"
+ }
+ ],
+ "step": 0,
+ "label": {
+ "label": "___PO_CODE_POWERSWITCH"
+ },
+ "emphasis": true,
+ "ruleEvent": true,
+ "ruleAction": false
+ },
+ {
+ "controlType": "List",
+ "name": "Audio Volume Command",
+ "controllable": true,
+ "property": "command",
+ "emphasis": false,
+ "link": {
+ "rt": "x.com.st.audiovolume",
+ "href": "/capability/audioVolume/main/0",
+ "if": "oic.if.a"
+ },
+ "iconUrl": {
+ "vector": "",
+ "small": "",
+ "large": "",
+ "mid": "icon://ic_function_audio_volume"
+ },
+ "alternatives": [
+ {
+ "value": "___PO_CODE_AUDIOVOLUME_INCREASE",
+ "key": "increase"
+ },
+ {
+ "value": "___PO_CODE_AUDIOVOLUME_DECREASE",
+ "key": "decrease"
+ },
+ {
+ "value": "___PO_CODE_AUDIOVOLUME_MAX",
+ "key": "max"
+ },
+ {
+ "value": "___PO_CODE_AUDIOVOLUME_MIN",
+ "key": "min"
+ }
+ ],
+ "step": 0,
+ "label": {
+ "label": "___PO_CODE_AUDIOVOLUME_COMMAND",
+ "n": "Audio Volume Command"
+ },
+ "ruleEvent": false,
+ "ruleAction": false,
+ "order": 4
+ },
+ {
+ "controlType": "List",
+ "name": "Audio Volume Command",
+ "controllable": true,
+ "property": "command",
+ "emphasis": false,
+ "link": {
+ "rt": "x.com.st.audiovolume",
+ "href": "/capability/audioVolume/main/0",
+ "if": "oic.if.a"
+ },
+ "iconUrl": {
+ "vector": "",
+ "small": "",
+ "large": "",
+ "mid": "icon://ic_function_audio_volume"
+ },
+ "alternatives": [
+ {
+ "value": "___PO_CODE_AUDIOVOLUME_INCREASE",
+ "key": "increase"
+ },
+ {
+ "value": "___PO_CODE_AUDIOVOLUME_DECREASE",
+ "key": "decrease"
+ },
+ {
+ "value": "___PO_CODE_AUDIOVOLUME_MAX",
+ "key": "max"
+ },
+ {
+ "value": "___PO_CODE_AUDIOVOLUME_MIN",
+ "key": "min"
+ }
+ ],
+ "step": 0,
+ "label": {
+ "label": "___PO_CODE_AUDIOVOLUME_COMMAND",
+ "n": "Audio Volume Command"
+ },
+ "ruleEvent": false,
+ "ruleAction": true,
+ "order": 5
+ },
+ {
+ "controlType": "List",
+ "name": "Audio Volume Command",
+ "controllable": true,
+ "property": "command",
+ "emphasis": false,
+ "link": {
+ "rt": "x.com.st.audiovolume",
+ "href": "/capability/audioVolume/main/0",
+ "if": "oic.if.a"
+ },
+ "iconUrl": {
+ "vector": "",
+ "small": "",
+ "large": "",
+ "mid": "icon://ic_function_audio_volume"
+ },
+ "alternatives": [
+ {
+ "value": "___PO_CODE_AUDIOVOLUME_INCREASE",
+ "key": "increase"
+ },
+ {
+ "value": "___PO_CODE_AUDIOVOLUME_DECREASE",
+ "key": "decrease"
+ },
+ {
+ "value": "___PO_CODE_AUDIOVOLUME_MAX",
+ "key": "max"
+ },
+ {
+ "value": "___PO_CODE_AUDIOVOLUME_MIN",
+ "key": "min"
+ }
+ ],
+ "step": 0,
+ "label": {
+ "label": "___PO_CODE_AUDIOVOLUME_COMMAND",
+ "n": "Audio Volume Command"
+ },
+ "ruleEvent": true,
+ "ruleAction": false,
+ "order": 6
+ },
+ {
+ "controlType": "slider",
+ "name": "Audio Volume",
+ "controllable": true,
+ "property": "volume",
+ "emphasis": false,
+ "link": {
+ "rt": "x.com.st.audiovolume",
+ "href": "/capability/audioVolume/main/0",
+ "if": "oic.if.a"
+ },
+ "iconUrl": {
+ "vector": "",
+ "small": "",
+ "large": "",
+ "mid": "icon://ic_function_audio_volume"
+ },
+ "range": [
+ 0,
+ 100
+ ],
+ "step": 0,
+ "label": {
+ "label": "___PO_CODE_AUDIOVOLUME_VOLUME",
+ "n": "Volume"
+ },
+ "ruleEvent": false,
+ "ruleAction": false,
+ "order": 7
+ },
+ {
+ "controlType": "slider",
+ "name": "Audio Volume",
+ "controllable": true,
+ "property": "volume",
+ "emphasis": false,
+ "link": {
+ "rt": "x.com.st.audiovolume",
+ "href": "/capability/audioVolume/main/0",
+ "if": "oic.if.a"
+ },
+ "iconUrl": {
+ "vector": "",
+ "small": "",
+ "large": "",
+ "mid": "icon://ic_function_audio_volume"
+ },
+ "range": [
+ 0,
+ 100
+ ],
+ "step": 0,
+ "label": {
+ "label": "___PO_CODE_AUDIOVOLUME_VOLUME",
+ "n": "Volume"
+ },
+ "ruleEvent": false,
+ "ruleAction": true,
+ "order": 8
+ },
+ {
+ "ruleAction": false,
+ "emphasis": false,
+ "controllable": false,
+ "step": 0,
+ "link": {
+ "rt": "oic.r.sensor.motion",
+ "href": "/capability/motionSensor/main/0",
+ "if": "oic.if.r"
+ },
+ "controlType": "List",
+ "name": "Motion Sensor",
+ "label": {
+ "label": "___PO_CODE_MOTIONSENSOR",
+ "n": "ST Motion Sensor resource"
+ },
+ "iconUrl": {
+ "mid": "icon://ic_function_motion_sensor",
+ "large": "",
+ "small": "",
+ "vector": ""
+ },
+ "ruleEvent": false,
+ "alternatives": [
+ {
+ "type": "inactive",
+ "value": "___PO_CODE_MOTIONSENSOR_NO_MOTION",
+ "key": "false"
+ },
+ {
+ "value": "___PO_CODE_MOTIONSENSOR_MOTION_DETECTED",
+ "key": "true"
+ }
+ ],
+ "order": 9,
+ "property": "value"
+ },
+ {
+ "ruleAction": false,
+ "emphasis": false,
+ "controllable": false,
+ "step": 0,
+ "link": {
+ "rt": "oic.r.sensor.motion",
+ "href": "/capability/motionSensor/main/0",
+ "if": "oic.if.r"
+ },
+ "controlType": "List",
+ "name": "Motion Sensor",
+ "label": {
+ "label": "___PO_CODE_MOTIONSENSOR",
+ "n": "ST Motion Sensor resource"
+ },
+ "iconUrl": {
+ "mid": "icon://ic_function_motion_sensor",
+ "large": "",
+ "small": "",
+ "vector": ""
+ },
+ "ruleEvent": true,
+ "alternatives": [
+ {
+ "type": "inactive",
+ "value": "___PO_CODE_MOTIONSENSOR_NO_MOTION",
+ "key": "false"
+ },
+ {
+ "value": "___PO_CODE_MOTIONSENSOR_MOTION_DETECTED",
+ "key": "true"
+ }
+ ],
+ "order": 10,
+ "property": "value"
+ },
+ {
+ "ruleAction": true,
+ "controllable": true,
+ "range": [
+ 1,
+ 100
+ ],
+ "link": {
+ "rt": "oic.r.light.dimming",
+ "href": "/capability/switchLevel/main/0",
+ "if": "oic.if.a"
+ },
+ "step": 0,
+ "controlType": "List",
+ "name": "Switch Level",
+ "label": {
+ "label": "___PO_CODE_SWITCHLEVEL_DIMMING",
+ "n": "st dimming level resource"
+ },
+ "emphasis": false,
+ "ruleEvent": false,
+ "iconUrl": {
+ "mid": "icon://ic_function_light_dimmer",
+ "large": "",
+ "small": "",
+ "vector": ""
+ },
+ "order": 11,
+ "property": "dimmingSetting"
+ },
+ {
+ "ruleAction": false,
+ "controllable": true,
+ "range": [
+ 1,
+ 100
+ ],
+ "link": {
+ "rt": "oic.r.light.dimming",
+ "href": "/capability/switchLevel/main/0",
+ "if": "oic.if.a"
+ },
+ "step": 0,
+ "controlType": "List",
+ "name": "Switch Level",
+ "label": {
+ "label": "___PO_CODE_SWITCHLEVEL_DIMMING",
+ "n": "st dimming level resource"
+ },
+ "emphasis": false,
+ "ruleEvent": false,
+ "iconUrl": {
+ "mid": "icon://ic_function_light_dimmer",
+ "large": "",
+ "small": "",
+ "vector": ""
+ },
+ "order": 12,
+ "property": "dimmingSetting"
+ }
+ ]
+}
--- /dev/null
+@-webkit-keyframes spinAround{from{-webkit-transform:rotate(0);transform:rotate(0)}to{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes spinAround{from{-webkit-transform:rotate(0);transform:rotate(0)}to{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.switch[type=checkbox]{outline:0;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;display:inline-block;position:absolute;opacity:0}.switch[type=checkbox][disabled]{cursor:not-allowed}.switch[type=checkbox][disabled]+label{opacity:.5}.switch[type=checkbox][disabled]+label::before{opacity:.5}.switch[type=checkbox][disabled]+label::after{opacity:.5}.switch[type=checkbox][disabled]+label:hover{cursor:not-allowed}.switch[type=checkbox]+label{position:relative;display:initial;font-size:1rem;line-height:initial;padding-left:3.5rem;padding-top:.2rem;cursor:pointer}.switch[type=checkbox]+label::before{position:absolute;display:block;top:0;left:0;width:3rem;height:1.5rem;border:.1rem solid transparent;border-radius:3px;background:#b5b5b5;content:''}.switch[type=checkbox]+label::after{display:block;position:absolute;top:.25rem;left:.25rem;width:1rem;height:1rem;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);border-radius:3px;background:#fff;-webkit-transition:all .25s ease-out;transition:all .25s ease-out;content:''}.switch[type=checkbox].is-rtl+label{padding-left:0;padding-right:3.5rem}.switch[type=checkbox].is-rtl+label::before{left:auto;right:0}.switch[type=checkbox].is-rtl+label::after{left:auto;right:.25rem}.switch[type=checkbox]:checked+label::before{background:#00d1b2}.switch[type=checkbox]:checked+label::after{left:1.625rem}.switch[type=checkbox]:checked.is-rtl+label::after{left:auto;right:1.625rem}.switch[type=checkbox].is-outlined+label::before{background-color:transparent;border-color:#b5b5b5}.switch[type=checkbox].is-outlined+label::after{background:#b5b5b5}.switch[type=checkbox].is-outlined:checked+label::before{background-color:transparent;border-color:#00d1b2}.switch[type=checkbox].is-outlined:checked+label::after{background:#00d1b2}.switch[type=checkbox].is-thin+label::before{top:.54545rem;height:.375rem}.switch[type=checkbox].is-thin+label::after{-webkit-box-shadow:0 0 3px #7a7a7a;box-shadow:0 0 3px #7a7a7a}.switch[type=checkbox].is-rounded+label::before{border-radius:20px}.switch[type=checkbox].is-rounded+label::after{border-radius:50%}.switch[type=checkbox].is-small+label{position:relative;display:initial;font-size:.75rem;line-height:initial;padding-left:2.75rem;padding-top:.2rem;cursor:pointer}.switch[type=checkbox].is-small+label::before{position:absolute;display:block;top:0;left:0;width:2.25rem;height:1.125rem;border:.1rem solid transparent;border-radius:3px;background:#b5b5b5;content:''}.switch[type=checkbox].is-small+label::after{display:block;position:absolute;top:.25rem;left:.25rem;width:.625rem;height:.625rem;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);border-radius:3px;background:#fff;-webkit-transition:all .25s ease-out;transition:all .25s ease-out;content:''}.switch[type=checkbox].is-small.is-rtl+label{padding-left:0;padding-right:2.75rem}.switch[type=checkbox].is-small.is-rtl+label::before{left:auto;right:0}.switch[type=checkbox].is-small.is-rtl+label::after{left:auto;right:.25rem}.switch[type=checkbox].is-small:checked+label::before{background:#00d1b2}.switch[type=checkbox].is-small:checked+label::after{left:1.25rem}.switch[type=checkbox].is-small:checked.is-rtl+label::after{left:auto;right:1.25rem}.switch[type=checkbox].is-small.is-outlined+label::before{background-color:transparent;border-color:#b5b5b5}.switch[type=checkbox].is-small.is-outlined+label::after{background:#b5b5b5}.switch[type=checkbox].is-small.is-outlined:checked+label::before{background-color:transparent;border-color:#00d1b2}.switch[type=checkbox].is-small.is-outlined:checked+label::after{background:#00d1b2}.switch[type=checkbox].is-small.is-thin+label::before{top:.40909rem;height:.28125rem}.switch[type=checkbox].is-small.is-thin+label::after{-webkit-box-shadow:0 0 3px #7a7a7a;box-shadow:0 0 3px #7a7a7a}.switch[type=checkbox].is-small.is-rounded+label::before{border-radius:20px}.switch[type=checkbox].is-small.is-rounded+label::after{border-radius:50%}.switch[type=checkbox].is-medium+label{position:relative;display:initial;font-size:1.25rem;line-height:initial;padding-left:4.25rem;padding-top:.2rem;cursor:pointer}.switch[type=checkbox].is-medium+label::before{position:absolute;display:block;top:0;left:0;width:3.75rem;height:1.875rem;border:.1rem solid transparent;border-radius:3px;background:#b5b5b5;content:''}.switch[type=checkbox].is-medium+label::after{display:block;position:absolute;top:.25rem;left:.25rem;width:1.375rem;height:1.375rem;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);border-radius:3px;background:#fff;-webkit-transition:all .25s ease-out;transition:all .25s ease-out;content:''}.switch[type=checkbox].is-medium.is-rtl+label{padding-left:0;padding-right:4.25rem}.switch[type=checkbox].is-medium.is-rtl+label::before{left:auto;right:0}.switch[type=checkbox].is-medium.is-rtl+label::after{left:auto;right:.25rem}.switch[type=checkbox].is-medium:checked+label::before{background:#00d1b2}.switch[type=checkbox].is-medium:checked+label::after{left:2rem}.switch[type=checkbox].is-medium:checked.is-rtl+label::after{left:auto;right:2rem}.switch[type=checkbox].is-medium.is-outlined+label::before{background-color:transparent;border-color:#b5b5b5}.switch[type=checkbox].is-medium.is-outlined+label::after{background:#b5b5b5}.switch[type=checkbox].is-medium.is-outlined:checked+label::before{background-color:transparent;border-color:#00d1b2}.switch[type=checkbox].is-medium.is-outlined:checked+label::after{background:#00d1b2}.switch[type=checkbox].is-medium.is-thin+label::before{top:.68182rem;height:.46875rem}.switch[type=checkbox].is-medium.is-thin+label::after{-webkit-box-shadow:0 0 3px #7a7a7a;box-shadow:0 0 3px #7a7a7a}.switch[type=checkbox].is-medium.is-rounded+label::before{border-radius:20px}.switch[type=checkbox].is-medium.is-rounded+label::after{border-radius:50%}.switch[type=checkbox].is-large+label{position:relative;display:initial;font-size:1.5rem;line-height:initial;padding-left:5rem;padding-top:.2rem;cursor:pointer}.switch[type=checkbox].is-large+label::before{position:absolute;display:block;top:0;left:0;width:4.5rem;height:2.25rem;border:.1rem solid transparent;border-radius:3px;background:#b5b5b5;content:''}.switch[type=checkbox].is-large+label::after{display:block;position:absolute;top:.25rem;left:.25rem;width:1.75rem;height:1.75rem;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);border-radius:3px;background:#fff;-webkit-transition:all .25s ease-out;transition:all .25s ease-out;content:''}.switch[type=checkbox].is-large.is-rtl+label{padding-left:0;padding-right:5rem}.switch[type=checkbox].is-large.is-rtl+label::before{left:auto;right:0}.switch[type=checkbox].is-large.is-rtl+label::after{left:auto;right:.25rem}.switch[type=checkbox].is-large:checked+label::before{background:#00d1b2}.switch[type=checkbox].is-large:checked+label::after{left:2.375rem}.switch[type=checkbox].is-large:checked.is-rtl+label::after{left:auto;right:2.375rem}.switch[type=checkbox].is-large.is-outlined+label::before{background-color:transparent;border-color:#b5b5b5}.switch[type=checkbox].is-large.is-outlined+label::after{background:#b5b5b5}.switch[type=checkbox].is-large.is-outlined:checked+label::before{background-color:transparent;border-color:#00d1b2}.switch[type=checkbox].is-large.is-outlined:checked+label::after{background:#00d1b2}.switch[type=checkbox].is-large.is-thin+label::before{top:.81818rem;height:.5625rem}.switch[type=checkbox].is-large.is-thin+label::after{-webkit-box-shadow:0 0 3px #7a7a7a;box-shadow:0 0 3px #7a7a7a}.switch[type=checkbox].is-large.is-rounded+label::before{border-radius:20px}.switch[type=checkbox].is-large.is-rounded+label::after{border-radius:50%}.switch[type=checkbox].is-white:checked+label::before{background:#fff}.switch[type=checkbox].is-white.is-outlined:checked+label::before{background-color:transparent;border-color:#fff!important}.switch[type=checkbox].is-white.is-outlined:checked+label::after{background:#fff}.switch[type=checkbox].is-white.is-thin.is-outlined+label::after{-webkit-box-shadow:none;box-shadow:none}.switch[type=checkbox].is-unchecked-white+label::before{background:#fff}.switch[type=checkbox].is-unchecked-white.is-outlined+label::before{background-color:transparent;border-color:#fff!important}.switch[type=checkbox].is-unchecked-white.is-outlined+label::after{background:#fff}.switch[type=checkbox].is-black:checked+label::before{background:#0a0a0a}.switch[type=checkbox].is-black.is-outlined:checked+label::before{background-color:transparent;border-color:#0a0a0a!important}.switch[type=checkbox].is-black.is-outlined:checked+label::after{background:#0a0a0a}.switch[type=checkbox].is-black.is-thin.is-outlined+label::after{-webkit-box-shadow:none;box-shadow:none}.switch[type=checkbox].is-unchecked-black+label::before{background:#0a0a0a}.switch[type=checkbox].is-unchecked-black.is-outlined+label::before{background-color:transparent;border-color:#0a0a0a!important}.switch[type=checkbox].is-unchecked-black.is-outlined+label::after{background:#0a0a0a}.switch[type=checkbox].is-light:checked+label::before{background:#f5f5f5}.switch[type=checkbox].is-light.is-outlined:checked+label::before{background-color:transparent;border-color:#f5f5f5!important}.switch[type=checkbox].is-light.is-outlined:checked+label::after{background:#f5f5f5}.switch[type=checkbox].is-light.is-thin.is-outlined+label::after{-webkit-box-shadow:none;box-shadow:none}.switch[type=checkbox].is-unchecked-light+label::before{background:#f5f5f5}.switch[type=checkbox].is-unchecked-light.is-outlined+label::before{background-color:transparent;border-color:#f5f5f5!important}.switch[type=checkbox].is-unchecked-light.is-outlined+label::after{background:#f5f5f5}.switch[type=checkbox].is-dark:checked+label::before{background:#363636}.switch[type=checkbox].is-dark.is-outlined:checked+label::before{background-color:transparent;border-color:#363636!important}.switch[type=checkbox].is-dark.is-outlined:checked+label::after{background:#363636}.switch[type=checkbox].is-dark.is-thin.is-outlined+label::after{-webkit-box-shadow:none;box-shadow:none}.switch[type=checkbox].is-unchecked-dark+label::before{background:#363636}.switch[type=checkbox].is-unchecked-dark.is-outlined+label::before{background-color:transparent;border-color:#363636!important}.switch[type=checkbox].is-unchecked-dark.is-outlined+label::after{background:#363636}.switch[type=checkbox].is-primary:checked+label::before{background:#00d1b2}.switch[type=checkbox].is-primary.is-outlined:checked+label::before{background-color:transparent;border-color:#00d1b2!important}.switch[type=checkbox].is-primary.is-outlined:checked+label::after{background:#00d1b2}.switch[type=checkbox].is-primary.is-thin.is-outlined+label::after{-webkit-box-shadow:none;box-shadow:none}.switch[type=checkbox].is-unchecked-primary+label::before{background:#00d1b2}.switch[type=checkbox].is-unchecked-primary.is-outlined+label::before{background-color:transparent;border-color:#00d1b2!important}.switch[type=checkbox].is-unchecked-primary.is-outlined+label::after{background:#00d1b2}.switch[type=checkbox].is-link:checked+label::before{background:#3273dc}.switch[type=checkbox].is-link.is-outlined:checked+label::before{background-color:transparent;border-color:#3273dc!important}.switch[type=checkbox].is-link.is-outlined:checked+label::after{background:#3273dc}.switch[type=checkbox].is-link.is-thin.is-outlined+label::after{-webkit-box-shadow:none;box-shadow:none}.switch[type=checkbox].is-unchecked-link+label::before{background:#3273dc}.switch[type=checkbox].is-unchecked-link.is-outlined+label::before{background-color:transparent;border-color:#3273dc!important}.switch[type=checkbox].is-unchecked-link.is-outlined+label::after{background:#3273dc}.switch[type=checkbox].is-info:checked+label::before{background:#209cee}.switch[type=checkbox].is-info.is-outlined:checked+label::before{background-color:transparent;border-color:#209cee!important}.switch[type=checkbox].is-info.is-outlined:checked+label::after{background:#209cee}.switch[type=checkbox].is-info.is-thin.is-outlined+label::after{-webkit-box-shadow:none;box-shadow:none}.switch[type=checkbox].is-unchecked-info+label::before{background:#209cee}.switch[type=checkbox].is-unchecked-info.is-outlined+label::before{background-color:transparent;border-color:#209cee!important}.switch[type=checkbox].is-unchecked-info.is-outlined+label::after{background:#209cee}.switch[type=checkbox].is-success:checked+label::before{background:#23d160}.switch[type=checkbox].is-success.is-outlined:checked+label::before{background-color:transparent;border-color:#23d160!important}.switch[type=checkbox].is-success.is-outlined:checked+label::after{background:#23d160}.switch[type=checkbox].is-success.is-thin.is-outlined+label::after{-webkit-box-shadow:none;box-shadow:none}.switch[type=checkbox].is-unchecked-success+label::before{background:#23d160}.switch[type=checkbox].is-unchecked-success.is-outlined+label::before{background-color:transparent;border-color:#23d160!important}.switch[type=checkbox].is-unchecked-success.is-outlined+label::after{background:#23d160}.switch[type=checkbox].is-warning:checked+label::before{background:#ffdd57}.switch[type=checkbox].is-warning.is-outlined:checked+label::before{background-color:transparent;border-color:#ffdd57!important}.switch[type=checkbox].is-warning.is-outlined:checked+label::after{background:#ffdd57}.switch[type=checkbox].is-warning.is-thin.is-outlined+label::after{-webkit-box-shadow:none;box-shadow:none}.switch[type=checkbox].is-unchecked-warning+label::before{background:#ffdd57}.switch[type=checkbox].is-unchecked-warning.is-outlined+label::before{background-color:transparent;border-color:#ffdd57!important}.switch[type=checkbox].is-unchecked-warning.is-outlined+label::after{background:#ffdd57}.switch[type=checkbox].is-danger:checked+label::before{background:#ff3860}.switch[type=checkbox].is-danger.is-outlined:checked+label::before{background-color:transparent;border-color:#ff3860!important}.switch[type=checkbox].is-danger.is-outlined:checked+label::after{background:#ff3860}.switch[type=checkbox].is-danger.is-thin.is-outlined+label::after{-webkit-box-shadow:none;box-shadow:none}.switch[type=checkbox].is-unchecked-danger+label::before{background:#ff3860}.switch[type=checkbox].is-unchecked-danger.is-outlined+label::before{background-color:transparent;border-color:#ff3860!important}.switch[type=checkbox].is-unchecked-danger.is-outlined+label::after{background:#ff3860}
\ No newline at end of file
--- /dev/null
+/*! bulma.io v0.6.2 | MIT License | github.com/jgthms/bulma */@-webkit-keyframes spinAround{from{-webkit-transform:rotate(0);transform:rotate(0)}to{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes spinAround{from{-webkit-transform:rotate(0);transform:rotate(0)}to{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}/*! minireset.css v0.0.2 | MIT License | github.com/jgthms/minireset.css */blockquote,body,dd,dl,dt,fieldset,figure,h1,h2,h3,h4,h5,h6,hr,html,iframe,legend,li,ol,p,pre,textarea,ul{margin:0;padding:0}h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:400}ul{list-style:none}button,input,select,textarea{margin:0}html{-webkit-box-sizing:border-box;box-sizing:border-box}*{-webkit-box-sizing:inherit;box-sizing:inherit}:after,:before{-webkit-box-sizing:inherit;box-sizing:inherit}audio,embed,img,object,video{max-width:100%}iframe{border:0}table{border-collapse:collapse;border-spacing:0}td,th{padding:0;text-align:left}html{background-color:#fff;font-size:16px;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;min-width:300px;overflow-x:hidden;overflow-y:scroll;text-rendering:optimizeLegibility;-webkit-text-size-adjust:100%;-moz-text-size-adjust:100%;-ms-text-size-adjust:100%;text-size-adjust:100%}article,aside,figure,footer,header,hgroup,section{display:block}body,button,input,select,textarea{font-family:BlinkMacSystemFont,-apple-system,"Segoe UI",Roboto,Oxygen,Ubuntu,Cantarell,"Fira Sans","Droid Sans","Helvetica Neue",Helvetica,Arial,sans-serif}code,pre{-moz-osx-font-smoothing:auto;-webkit-font-smoothing:auto;font-family:monospace}body{color:#4a4a4a;font-size:1rem;font-weight:400;line-height:1.5}a{color:#3273dc;cursor:pointer;text-decoration:none}a strong{color:currentColor}a:hover{color:#363636}code{background-color:#f5f5f5;color:#ff3860;font-size:.875em;font-weight:400;padding:.25em .5em .25em}hr{background-color:#dbdbdb;border:none;display:block;height:1px;margin:1.5rem 0}img{height:auto;max-width:100%}input[type=checkbox],input[type=radio]{vertical-align:baseline}small{font-size:.875em}span{font-style:inherit;font-weight:inherit}strong{color:#363636;font-weight:700}pre{-webkit-overflow-scrolling:touch;background-color:#f5f5f5;color:#4a4a4a;font-size:.875em;overflow-x:auto;padding:1.25rem 1.5rem;white-space:pre;word-wrap:normal}pre code{background-color:transparent;color:currentColor;font-size:1em;padding:0}table td,table th{text-align:left;vertical-align:top}table th{color:#363636}.is-clearfix:after{clear:both;content:" ";display:table}.is-pulled-left{float:left!important}.is-pulled-right{float:right!important}.is-clipped{overflow:hidden!important}.is-overlay{bottom:0;left:0;position:absolute;right:0;top:0}.is-size-1{font-size:3rem!important}.is-size-2{font-size:2.5rem!important}.is-size-3{font-size:2rem!important}.is-size-4{font-size:1.5rem!important}.is-size-5{font-size:1.25rem!important}.is-size-6{font-size:1rem!important}.is-size-7{font-size:.75rem!important}@media screen and (max-width:768px){.is-size-1-mobile{font-size:3rem!important}.is-size-2-mobile{font-size:2.5rem!important}.is-size-3-mobile{font-size:2rem!important}.is-size-4-mobile{font-size:1.5rem!important}.is-size-5-mobile{font-size:1.25rem!important}.is-size-6-mobile{font-size:1rem!important}.is-size-7-mobile{font-size:.75rem!important}}@media screen and (min-width:769px),print{.is-size-1-tablet{font-size:3rem!important}.is-size-2-tablet{font-size:2.5rem!important}.is-size-3-tablet{font-size:2rem!important}.is-size-4-tablet{font-size:1.5rem!important}.is-size-5-tablet{font-size:1.25rem!important}.is-size-6-tablet{font-size:1rem!important}.is-size-7-tablet{font-size:.75rem!important}}@media screen and (max-width:1023px){.is-size-1-touch{font-size:3rem!important}.is-size-2-touch{font-size:2.5rem!important}.is-size-3-touch{font-size:2rem!important}.is-size-4-touch{font-size:1.5rem!important}.is-size-5-touch{font-size:1.25rem!important}.is-size-6-touch{font-size:1rem!important}.is-size-7-touch{font-size:.75rem!important}}@media screen and (min-width:1024px){.is-size-1-desktop{font-size:3rem!important}.is-size-2-desktop{font-size:2.5rem!important}.is-size-3-desktop{font-size:2rem!important}.is-size-4-desktop{font-size:1.5rem!important}.is-size-5-desktop{font-size:1.25rem!important}.is-size-6-desktop{font-size:1rem!important}.is-size-7-desktop{font-size:.75rem!important}}@media screen and (min-width:1216px){.is-size-1-widescreen{font-size:3rem!important}.is-size-2-widescreen{font-size:2.5rem!important}.is-size-3-widescreen{font-size:2rem!important}.is-size-4-widescreen{font-size:1.5rem!important}.is-size-5-widescreen{font-size:1.25rem!important}.is-size-6-widescreen{font-size:1rem!important}.is-size-7-widescreen{font-size:.75rem!important}}@media screen and (min-width:1408px){.is-size-1-fullhd{font-size:3rem!important}.is-size-2-fullhd{font-size:2.5rem!important}.is-size-3-fullhd{font-size:2rem!important}.is-size-4-fullhd{font-size:1.5rem!important}.is-size-5-fullhd{font-size:1.25rem!important}.is-size-6-fullhd{font-size:1rem!important}.is-size-7-fullhd{font-size:.75rem!important}}.has-text-centered{text-align:center!important}@media screen and (max-width:768px){.has-text-centered-mobile{text-align:center!important}}@media screen and (min-width:769px),print{.has-text-centered-tablet{text-align:center!important}}@media screen and (min-width:769px) and (max-width:1023px){.has-text-centered-tablet-only{text-align:center!important}}@media screen and (max-width:1023px){.has-text-centered-touch{text-align:center!important}}@media screen and (min-width:1024px){.has-text-centered-desktop{text-align:center!important}}@media screen and (min-width:1024px) and (max-width:1215px){.has-text-centered-desktop-only{text-align:center!important}}@media screen and (min-width:1216px){.has-text-centered-widescreen{text-align:center!important}}@media screen and (min-width:1216px) and (max-width:1407px){.has-text-centered-widescreen-only{text-align:center!important}}@media screen and (min-width:1408px){.has-text-centered-fullhd{text-align:center!important}}.has-text-justified{text-align:justify!important}@media screen and (max-width:768px){.has-text-justified-mobile{text-align:justify!important}}@media screen and (min-width:769px),print{.has-text-justified-tablet{text-align:justify!important}}@media screen and (min-width:769px) and (max-width:1023px){.has-text-justified-tablet-only{text-align:justify!important}}@media screen and (max-width:1023px){.has-text-justified-touch{text-align:justify!important}}@media screen and (min-width:1024px){.has-text-justified-desktop{text-align:justify!important}}@media screen and (min-width:1024px) and (max-width:1215px){.has-text-justified-desktop-only{text-align:justify!important}}@media screen and (min-width:1216px){.has-text-justified-widescreen{text-align:justify!important}}@media screen and (min-width:1216px) and (max-width:1407px){.has-text-justified-widescreen-only{text-align:justify!important}}@media screen and (min-width:1408px){.has-text-justified-fullhd{text-align:justify!important}}.has-text-left{text-align:left!important}@media screen and (max-width:768px){.has-text-left-mobile{text-align:left!important}}@media screen and (min-width:769px),print{.has-text-left-tablet{text-align:left!important}}@media screen and (min-width:769px) and (max-width:1023px){.has-text-left-tablet-only{text-align:left!important}}@media screen and (max-width:1023px){.has-text-left-touch{text-align:left!important}}@media screen and (min-width:1024px){.has-text-left-desktop{text-align:left!important}}@media screen and (min-width:1024px) and (max-width:1215px){.has-text-left-desktop-only{text-align:left!important}}@media screen and (min-width:1216px){.has-text-left-widescreen{text-align:left!important}}@media screen and (min-width:1216px) and (max-width:1407px){.has-text-left-widescreen-only{text-align:left!important}}@media screen and (min-width:1408px){.has-text-left-fullhd{text-align:left!important}}.has-text-right{text-align:right!important}@media screen and (max-width:768px){.has-text-right-mobile{text-align:right!important}}@media screen and (min-width:769px),print{.has-text-right-tablet{text-align:right!important}}@media screen and (min-width:769px) and (max-width:1023px){.has-text-right-tablet-only{text-align:right!important}}@media screen and (max-width:1023px){.has-text-right-touch{text-align:right!important}}@media screen and (min-width:1024px){.has-text-right-desktop{text-align:right!important}}@media screen and (min-width:1024px) and (max-width:1215px){.has-text-right-desktop-only{text-align:right!important}}@media screen and (min-width:1216px){.has-text-right-widescreen{text-align:right!important}}@media screen and (min-width:1216px) and (max-width:1407px){.has-text-right-widescreen-only{text-align:right!important}}@media screen and (min-width:1408px){.has-text-right-fullhd{text-align:right!important}}.is-capitalized{text-transform:capitalize!important}.is-lowercase{text-transform:lowercase!important}.is-uppercase{text-transform:uppercase!important}.is-italic{font-style:italic!important}.has-text-white{color:#fff!important}a.has-text-white:focus,a.has-text-white:hover{color:#e6e6e6!important}.has-text-black{color:#0a0a0a!important}a.has-text-black:focus,a.has-text-black:hover{color:#000!important}.has-text-light{color:#f5f5f5!important}a.has-text-light:focus,a.has-text-light:hover{color:#dbdbdb!important}.has-text-dark{color:#363636!important}a.has-text-dark:focus,a.has-text-dark:hover{color:#1c1c1c!important}.has-text-primary{color:#00d1b2!important}a.has-text-primary:focus,a.has-text-primary:hover{color:#009e86!important}.has-text-link{color:#3273dc!important}a.has-text-link:focus,a.has-text-link:hover{color:#205bbc!important}.has-text-info{color:#209cee!important}a.has-text-info:focus,a.has-text-info:hover{color:#0f81cc!important}.has-text-success{color:#23d160!important}a.has-text-success:focus,a.has-text-success:hover{color:#1ca64c!important}.has-text-warning{color:#ffdd57!important}a.has-text-warning:focus,a.has-text-warning:hover{color:#ffd324!important}.has-text-danger{color:#ff3860!important}a.has-text-danger:focus,a.has-text-danger:hover{color:#ff0537!important}.has-text-black-bis{color:#121212!important}.has-text-black-ter{color:#242424!important}.has-text-grey-darker{color:#363636!important}.has-text-grey-dark{color:#4a4a4a!important}.has-text-grey{color:#7a7a7a!important}.has-text-grey-light{color:#b5b5b5!important}.has-text-grey-lighter{color:#dbdbdb!important}.has-text-white-ter{color:#f5f5f5!important}.has-text-white-bis{color:#fafafa!important}.has-text-weight-light{font-weight:300!important}.has-text-weight-normal{font-weight:400!important}.has-text-weight-semibold{font-weight:600!important}.has-text-weight-bold{font-weight:700!important}.is-block{display:block!important}@media screen and (max-width:768px){.is-block-mobile{display:block!important}}@media screen and (min-width:769px),print{.is-block-tablet{display:block!important}}@media screen and (min-width:769px) and (max-width:1023px){.is-block-tablet-only{display:block!important}}@media screen and (max-width:1023px){.is-block-touch{display:block!important}}@media screen and (min-width:1024px){.is-block-desktop{display:block!important}}@media screen and (min-width:1024px) and (max-width:1215px){.is-block-desktop-only{display:block!important}}@media screen and (min-width:1216px){.is-block-widescreen{display:block!important}}@media screen and (min-width:1216px) and (max-width:1407px){.is-block-widescreen-only{display:block!important}}@media screen and (min-width:1408px){.is-block-fullhd{display:block!important}}.is-flex{display:-webkit-box!important;display:-ms-flexbox!important;display:flex!important}@media screen and (max-width:768px){.is-flex-mobile{display:-webkit-box!important;display:-ms-flexbox!important;display:flex!important}}@media screen and (min-width:769px),print{.is-flex-tablet{display:-webkit-box!important;display:-ms-flexbox!important;display:flex!important}}@media screen and (min-width:769px) and (max-width:1023px){.is-flex-tablet-only{display:-webkit-box!important;display:-ms-flexbox!important;display:flex!important}}@media screen and (max-width:1023px){.is-flex-touch{display:-webkit-box!important;display:-ms-flexbox!important;display:flex!important}}@media screen and (min-width:1024px){.is-flex-desktop{display:-webkit-box!important;display:-ms-flexbox!important;display:flex!important}}@media screen and (min-width:1024px) and (max-width:1215px){.is-flex-desktop-only{display:-webkit-box!important;display:-ms-flexbox!important;display:flex!important}}@media screen and (min-width:1216px){.is-flex-widescreen{display:-webkit-box!important;display:-ms-flexbox!important;display:flex!important}}@media screen and (min-width:1216px) and (max-width:1407px){.is-flex-widescreen-only{display:-webkit-box!important;display:-ms-flexbox!important;display:flex!important}}@media screen and (min-width:1408px){.is-flex-fullhd{display:-webkit-box!important;display:-ms-flexbox!important;display:flex!important}}.is-inline{display:inline!important}@media screen and (max-width:768px){.is-inline-mobile{display:inline!important}}@media screen and (min-width:769px),print{.is-inline-tablet{display:inline!important}}@media screen and (min-width:769px) and (max-width:1023px){.is-inline-tablet-only{display:inline!important}}@media screen and (max-width:1023px){.is-inline-touch{display:inline!important}}@media screen and (min-width:1024px){.is-inline-desktop{display:inline!important}}@media screen and (min-width:1024px) and (max-width:1215px){.is-inline-desktop-only{display:inline!important}}@media screen and (min-width:1216px){.is-inline-widescreen{display:inline!important}}@media screen and (min-width:1216px) and (max-width:1407px){.is-inline-widescreen-only{display:inline!important}}@media screen and (min-width:1408px){.is-inline-fullhd{display:inline!important}}.is-inline-block{display:inline-block!important}@media screen and (max-width:768px){.is-inline-block-mobile{display:inline-block!important}}@media screen and (min-width:769px),print{.is-inline-block-tablet{display:inline-block!important}}@media screen and (min-width:769px) and (max-width:1023px){.is-inline-block-tablet-only{display:inline-block!important}}@media screen and (max-width:1023px){.is-inline-block-touch{display:inline-block!important}}@media screen and (min-width:1024px){.is-inline-block-desktop{display:inline-block!important}}@media screen and (min-width:1024px) and (max-width:1215px){.is-inline-block-desktop-only{display:inline-block!important}}@media screen and (min-width:1216px){.is-inline-block-widescreen{display:inline-block!important}}@media screen and (min-width:1216px) and (max-width:1407px){.is-inline-block-widescreen-only{display:inline-block!important}}@media screen and (min-width:1408px){.is-inline-block-fullhd{display:inline-block!important}}.is-inline-flex{display:-webkit-inline-box!important;display:-ms-inline-flexbox!important;display:inline-flex!important}@media screen and (max-width:768px){.is-inline-flex-mobile{display:-webkit-inline-box!important;display:-ms-inline-flexbox!important;display:inline-flex!important}}@media screen and (min-width:769px),print{.is-inline-flex-tablet{display:-webkit-inline-box!important;display:-ms-inline-flexbox!important;display:inline-flex!important}}@media screen and (min-width:769px) and (max-width:1023px){.is-inline-flex-tablet-only{display:-webkit-inline-box!important;display:-ms-inline-flexbox!important;display:inline-flex!important}}@media screen and (max-width:1023px){.is-inline-flex-touch{display:-webkit-inline-box!important;display:-ms-inline-flexbox!important;display:inline-flex!important}}@media screen and (min-width:1024px){.is-inline-flex-desktop{display:-webkit-inline-box!important;display:-ms-inline-flexbox!important;display:inline-flex!important}}@media screen and (min-width:1024px) and (max-width:1215px){.is-inline-flex-desktop-only{display:-webkit-inline-box!important;display:-ms-inline-flexbox!important;display:inline-flex!important}}@media screen and (min-width:1216px){.is-inline-flex-widescreen{display:-webkit-inline-box!important;display:-ms-inline-flexbox!important;display:inline-flex!important}}@media screen and (min-width:1216px) and (max-width:1407px){.is-inline-flex-widescreen-only{display:-webkit-inline-box!important;display:-ms-inline-flexbox!important;display:inline-flex!important}}@media screen and (min-width:1408px){.is-inline-flex-fullhd{display:-webkit-inline-box!important;display:-ms-inline-flexbox!important;display:inline-flex!important}}.is-hidden{display:none!important}@media screen and (max-width:768px){.is-hidden-mobile{display:none!important}}@media screen and (min-width:769px),print{.is-hidden-tablet{display:none!important}}@media screen and (min-width:769px) and (max-width:1023px){.is-hidden-tablet-only{display:none!important}}@media screen and (max-width:1023px){.is-hidden-touch{display:none!important}}@media screen and (min-width:1024px){.is-hidden-desktop{display:none!important}}@media screen and (min-width:1024px) and (max-width:1215px){.is-hidden-desktop-only{display:none!important}}@media screen and (min-width:1216px){.is-hidden-widescreen{display:none!important}}@media screen and (min-width:1216px) and (max-width:1407px){.is-hidden-widescreen-only{display:none!important}}@media screen and (min-width:1408px){.is-hidden-fullhd{display:none!important}}.is-invisible{visibility:hidden!important}@media screen and (max-width:768px){.is-invisible-mobile{visibility:hidden!important}}@media screen and (min-width:769px),print{.is-invisible-tablet{visibility:hidden!important}}@media screen and (min-width:769px) and (max-width:1023px){.is-invisible-tablet-only{visibility:hidden!important}}@media screen and (max-width:1023px){.is-invisible-touch{visibility:hidden!important}}@media screen and (min-width:1024px){.is-invisible-desktop{visibility:hidden!important}}@media screen and (min-width:1024px) and (max-width:1215px){.is-invisible-desktop-only{visibility:hidden!important}}@media screen and (min-width:1216px){.is-invisible-widescreen{visibility:hidden!important}}@media screen and (min-width:1216px) and (max-width:1407px){.is-invisible-widescreen-only{visibility:hidden!important}}@media screen and (min-width:1408px){.is-invisible-fullhd{visibility:hidden!important}}.is-marginless{margin:0!important}.is-paddingless{padding:0!important}.is-radiusless{border-radius:0!important}.is-shadowless{-webkit-box-shadow:none!important;box-shadow:none!important}.is-unselectable{-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.box{background-color:#fff;border-radius:5px;-webkit-box-shadow:0 2px 3px rgba(10,10,10,.1),0 0 0 1px rgba(10,10,10,.1);box-shadow:0 2px 3px rgba(10,10,10,.1),0 0 0 1px rgba(10,10,10,.1);color:#4a4a4a;display:block;padding:1.25rem}.box:not(:last-child){margin-bottom:1.5rem}a.box:focus,a.box:hover{-webkit-box-shadow:0 2px 3px rgba(10,10,10,.1),0 0 0 1px #3273dc;box-shadow:0 2px 3px rgba(10,10,10,.1),0 0 0 1px #3273dc}a.box:active{-webkit-box-shadow:inset 0 1px 2px rgba(10,10,10,.2),0 0 0 1px #3273dc;box-shadow:inset 0 1px 2px rgba(10,10,10,.2),0 0 0 1px #3273dc}.button{-moz-appearance:none;-webkit-appearance:none;-webkit-box-align:center;-ms-flex-align:center;align-items:center;border:1px solid transparent;border-radius:3px;-webkit-box-shadow:none;box-shadow:none;display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;font-size:1rem;height:2.25em;-webkit-box-pack:start;-ms-flex-pack:start;justify-content:flex-start;line-height:1.5;padding-bottom:calc(.375em - 1px);padding-left:calc(.625em - 1px);padding-right:calc(.625em - 1px);padding-top:calc(.375em - 1px);position:relative;vertical-align:top;-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-color:#fff;border-color:#dbdbdb;color:#363636;cursor:pointer;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;padding-left:.75em;padding-right:.75em;text-align:center;white-space:nowrap}.button.is-active,.button.is-focused,.button:active,.button:focus{outline:0}.button[disabled]{cursor:not-allowed}.button strong{color:inherit}.button .icon,.button .icon.is-large,.button .icon.is-medium,.button .icon.is-small{height:1.5em;width:1.5em}.button .icon:first-child:not(:last-child){margin-left:calc(-.375em - 1px);margin-right:.1875em}.button .icon:last-child:not(:first-child){margin-left:.1875em;margin-right:calc(-.375em - 1px)}.button .icon:first-child:last-child{margin-left:calc(-.375em - 1px);margin-right:calc(-.375em - 1px)}.button.is-hovered,.button:hover{border-color:#b5b5b5;color:#363636}.button.is-focused,.button:focus{border-color:#3273dc;color:#363636}.button.is-focused:not(:active),.button:focus:not(:active){-webkit-box-shadow:0 0 0 .125em rgba(50,115,220,.25);box-shadow:0 0 0 .125em rgba(50,115,220,.25)}.button.is-active,.button:active{border-color:#4a4a4a;color:#363636}.button.is-text{background-color:transparent;border-color:transparent;color:#4a4a4a;text-decoration:underline}.button.is-text.is-focused,.button.is-text.is-hovered,.button.is-text:focus,.button.is-text:hover{background-color:#f5f5f5;color:#363636}.button.is-text.is-active,.button.is-text:active{background-color:#e8e8e8;color:#363636}.button.is-text[disabled]{background-color:transparent;border-color:transparent;-webkit-box-shadow:none;box-shadow:none}.button.is-white{background-color:#fff;border-color:transparent;color:#0a0a0a}.button.is-white.is-hovered,.button.is-white:hover{background-color:#f9f9f9;border-color:transparent;color:#0a0a0a}.button.is-white.is-focused,.button.is-white:focus{border-color:transparent;color:#0a0a0a}.button.is-white.is-focused:not(:active),.button.is-white:focus:not(:active){-webkit-box-shadow:0 0 0 .125em rgba(255,255,255,.25);box-shadow:0 0 0 .125em rgba(255,255,255,.25)}.button.is-white.is-active,.button.is-white:active{background-color:#f2f2f2;border-color:transparent;color:#0a0a0a}.button.is-white[disabled]{background-color:#fff;border-color:transparent;-webkit-box-shadow:none;box-shadow:none}.button.is-white.is-inverted{background-color:#0a0a0a;color:#fff}.button.is-white.is-inverted:hover{background-color:#000}.button.is-white.is-inverted[disabled]{background-color:#0a0a0a;border-color:transparent;-webkit-box-shadow:none;box-shadow:none;color:#fff}.button.is-white.is-loading:after{border-color:transparent transparent #0a0a0a #0a0a0a!important}.button.is-white.is-outlined{background-color:transparent;border-color:#fff;color:#fff}.button.is-white.is-outlined:focus,.button.is-white.is-outlined:hover{background-color:#fff;border-color:#fff;color:#0a0a0a}.button.is-white.is-outlined.is-loading:after{border-color:transparent transparent #fff #fff!important}.button.is-white.is-outlined[disabled]{background-color:transparent;border-color:#fff;-webkit-box-shadow:none;box-shadow:none;color:#fff}.button.is-white.is-inverted.is-outlined{background-color:transparent;border-color:#0a0a0a;color:#0a0a0a}.button.is-white.is-inverted.is-outlined:focus,.button.is-white.is-inverted.is-outlined:hover{background-color:#0a0a0a;color:#fff}.button.is-white.is-inverted.is-outlined[disabled]{background-color:transparent;border-color:#0a0a0a;-webkit-box-shadow:none;box-shadow:none;color:#0a0a0a}.button.is-black{background-color:#0a0a0a;border-color:transparent;color:#fff}.button.is-black.is-hovered,.button.is-black:hover{background-color:#040404;border-color:transparent;color:#fff}.button.is-black.is-focused,.button.is-black:focus{border-color:transparent;color:#fff}.button.is-black.is-focused:not(:active),.button.is-black:focus:not(:active){-webkit-box-shadow:0 0 0 .125em rgba(10,10,10,.25);box-shadow:0 0 0 .125em rgba(10,10,10,.25)}.button.is-black.is-active,.button.is-black:active{background-color:#000;border-color:transparent;color:#fff}.button.is-black[disabled]{background-color:#0a0a0a;border-color:transparent;-webkit-box-shadow:none;box-shadow:none}.button.is-black.is-inverted{background-color:#fff;color:#0a0a0a}.button.is-black.is-inverted:hover{background-color:#f2f2f2}.button.is-black.is-inverted[disabled]{background-color:#fff;border-color:transparent;-webkit-box-shadow:none;box-shadow:none;color:#0a0a0a}.button.is-black.is-loading:after{border-color:transparent transparent #fff #fff!important}.button.is-black.is-outlined{background-color:transparent;border-color:#0a0a0a;color:#0a0a0a}.button.is-black.is-outlined:focus,.button.is-black.is-outlined:hover{background-color:#0a0a0a;border-color:#0a0a0a;color:#fff}.button.is-black.is-outlined.is-loading:after{border-color:transparent transparent #0a0a0a #0a0a0a!important}.button.is-black.is-outlined[disabled]{background-color:transparent;border-color:#0a0a0a;-webkit-box-shadow:none;box-shadow:none;color:#0a0a0a}.button.is-black.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}.button.is-black.is-inverted.is-outlined:focus,.button.is-black.is-inverted.is-outlined:hover{background-color:#fff;color:#0a0a0a}.button.is-black.is-inverted.is-outlined[disabled]{background-color:transparent;border-color:#fff;-webkit-box-shadow:none;box-shadow:none;color:#fff}.button.is-light{background-color:#f5f5f5;border-color:transparent;color:#363636}.button.is-light.is-hovered,.button.is-light:hover{background-color:#eee;border-color:transparent;color:#363636}.button.is-light.is-focused,.button.is-light:focus{border-color:transparent;color:#363636}.button.is-light.is-focused:not(:active),.button.is-light:focus:not(:active){-webkit-box-shadow:0 0 0 .125em rgba(245,245,245,.25);box-shadow:0 0 0 .125em rgba(245,245,245,.25)}.button.is-light.is-active,.button.is-light:active{background-color:#e8e8e8;border-color:transparent;color:#363636}.button.is-light[disabled]{background-color:#f5f5f5;border-color:transparent;-webkit-box-shadow:none;box-shadow:none}.button.is-light.is-inverted{background-color:#363636;color:#f5f5f5}.button.is-light.is-inverted:hover{background-color:#292929}.button.is-light.is-inverted[disabled]{background-color:#363636;border-color:transparent;-webkit-box-shadow:none;box-shadow:none;color:#f5f5f5}.button.is-light.is-loading:after{border-color:transparent transparent #363636 #363636!important}.button.is-light.is-outlined{background-color:transparent;border-color:#f5f5f5;color:#f5f5f5}.button.is-light.is-outlined:focus,.button.is-light.is-outlined:hover{background-color:#f5f5f5;border-color:#f5f5f5;color:#363636}.button.is-light.is-outlined.is-loading:after{border-color:transparent transparent #f5f5f5 #f5f5f5!important}.button.is-light.is-outlined[disabled]{background-color:transparent;border-color:#f5f5f5;-webkit-box-shadow:none;box-shadow:none;color:#f5f5f5}.button.is-light.is-inverted.is-outlined{background-color:transparent;border-color:#363636;color:#363636}.button.is-light.is-inverted.is-outlined:focus,.button.is-light.is-inverted.is-outlined:hover{background-color:#363636;color:#f5f5f5}.button.is-light.is-inverted.is-outlined[disabled]{background-color:transparent;border-color:#363636;-webkit-box-shadow:none;box-shadow:none;color:#363636}.button.is-dark{background-color:#363636;border-color:transparent;color:#f5f5f5}.button.is-dark.is-hovered,.button.is-dark:hover{background-color:#2f2f2f;border-color:transparent;color:#f5f5f5}.button.is-dark.is-focused,.button.is-dark:focus{border-color:transparent;color:#f5f5f5}.button.is-dark.is-focused:not(:active),.button.is-dark:focus:not(:active){-webkit-box-shadow:0 0 0 .125em rgba(54,54,54,.25);box-shadow:0 0 0 .125em rgba(54,54,54,.25)}.button.is-dark.is-active,.button.is-dark:active{background-color:#292929;border-color:transparent;color:#f5f5f5}.button.is-dark[disabled]{background-color:#363636;border-color:transparent;-webkit-box-shadow:none;box-shadow:none}.button.is-dark.is-inverted{background-color:#f5f5f5;color:#363636}.button.is-dark.is-inverted:hover{background-color:#e8e8e8}.button.is-dark.is-inverted[disabled]{background-color:#f5f5f5;border-color:transparent;-webkit-box-shadow:none;box-shadow:none;color:#363636}.button.is-dark.is-loading:after{border-color:transparent transparent #f5f5f5 #f5f5f5!important}.button.is-dark.is-outlined{background-color:transparent;border-color:#363636;color:#363636}.button.is-dark.is-outlined:focus,.button.is-dark.is-outlined:hover{background-color:#363636;border-color:#363636;color:#f5f5f5}.button.is-dark.is-outlined.is-loading:after{border-color:transparent transparent #363636 #363636!important}.button.is-dark.is-outlined[disabled]{background-color:transparent;border-color:#363636;-webkit-box-shadow:none;box-shadow:none;color:#363636}.button.is-dark.is-inverted.is-outlined{background-color:transparent;border-color:#f5f5f5;color:#f5f5f5}.button.is-dark.is-inverted.is-outlined:focus,.button.is-dark.is-inverted.is-outlined:hover{background-color:#f5f5f5;color:#363636}.button.is-dark.is-inverted.is-outlined[disabled]{background-color:transparent;border-color:#f5f5f5;-webkit-box-shadow:none;box-shadow:none;color:#f5f5f5}.button.is-primary{background-color:#00d1b2;border-color:transparent;color:#fff}.button.is-primary.is-hovered,.button.is-primary:hover{background-color:#00c4a7;border-color:transparent;color:#fff}.button.is-primary.is-focused,.button.is-primary:focus{border-color:transparent;color:#fff}.button.is-primary.is-focused:not(:active),.button.is-primary:focus:not(:active){-webkit-box-shadow:0 0 0 .125em rgba(0,209,178,.25);box-shadow:0 0 0 .125em rgba(0,209,178,.25)}.button.is-primary.is-active,.button.is-primary:active{background-color:#00b89c;border-color:transparent;color:#fff}.button.is-primary[disabled]{background-color:#00d1b2;border-color:transparent;-webkit-box-shadow:none;box-shadow:none}.button.is-primary.is-inverted{background-color:#fff;color:#00d1b2}.button.is-primary.is-inverted:hover{background-color:#f2f2f2}.button.is-primary.is-inverted[disabled]{background-color:#fff;border-color:transparent;-webkit-box-shadow:none;box-shadow:none;color:#00d1b2}.button.is-primary.is-loading:after{border-color:transparent transparent #fff #fff!important}.button.is-primary.is-outlined{background-color:transparent;border-color:#00d1b2;color:#00d1b2}.button.is-primary.is-outlined:focus,.button.is-primary.is-outlined:hover{background-color:#00d1b2;border-color:#00d1b2;color:#fff}.button.is-primary.is-outlined.is-loading:after{border-color:transparent transparent #00d1b2 #00d1b2!important}.button.is-primary.is-outlined[disabled]{background-color:transparent;border-color:#00d1b2;-webkit-box-shadow:none;box-shadow:none;color:#00d1b2}.button.is-primary.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}.button.is-primary.is-inverted.is-outlined:focus,.button.is-primary.is-inverted.is-outlined:hover{background-color:#fff;color:#00d1b2}.button.is-primary.is-inverted.is-outlined[disabled]{background-color:transparent;border-color:#fff;-webkit-box-shadow:none;box-shadow:none;color:#fff}.button.is-link{background-color:#3273dc;border-color:transparent;color:#fff}.button.is-link.is-hovered,.button.is-link:hover{background-color:#276cda;border-color:transparent;color:#fff}.button.is-link.is-focused,.button.is-link:focus{border-color:transparent;color:#fff}.button.is-link.is-focused:not(:active),.button.is-link:focus:not(:active){-webkit-box-shadow:0 0 0 .125em rgba(50,115,220,.25);box-shadow:0 0 0 .125em rgba(50,115,220,.25)}.button.is-link.is-active,.button.is-link:active{background-color:#2366d1;border-color:transparent;color:#fff}.button.is-link[disabled]{background-color:#3273dc;border-color:transparent;-webkit-box-shadow:none;box-shadow:none}.button.is-link.is-inverted{background-color:#fff;color:#3273dc}.button.is-link.is-inverted:hover{background-color:#f2f2f2}.button.is-link.is-inverted[disabled]{background-color:#fff;border-color:transparent;-webkit-box-shadow:none;box-shadow:none;color:#3273dc}.button.is-link.is-loading:after{border-color:transparent transparent #fff #fff!important}.button.is-link.is-outlined{background-color:transparent;border-color:#3273dc;color:#3273dc}.button.is-link.is-outlined:focus,.button.is-link.is-outlined:hover{background-color:#3273dc;border-color:#3273dc;color:#fff}.button.is-link.is-outlined.is-loading:after{border-color:transparent transparent #3273dc #3273dc!important}.button.is-link.is-outlined[disabled]{background-color:transparent;border-color:#3273dc;-webkit-box-shadow:none;box-shadow:none;color:#3273dc}.button.is-link.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}.button.is-link.is-inverted.is-outlined:focus,.button.is-link.is-inverted.is-outlined:hover{background-color:#fff;color:#3273dc}.button.is-link.is-inverted.is-outlined[disabled]{background-color:transparent;border-color:#fff;-webkit-box-shadow:none;box-shadow:none;color:#fff}.button.is-info{background-color:#209cee;border-color:transparent;color:#fff}.button.is-info.is-hovered,.button.is-info:hover{background-color:#1496ed;border-color:transparent;color:#fff}.button.is-info.is-focused,.button.is-info:focus{border-color:transparent;color:#fff}.button.is-info.is-focused:not(:active),.button.is-info:focus:not(:active){-webkit-box-shadow:0 0 0 .125em rgba(32,156,238,.25);box-shadow:0 0 0 .125em rgba(32,156,238,.25)}.button.is-info.is-active,.button.is-info:active{background-color:#118fe4;border-color:transparent;color:#fff}.button.is-info[disabled]{background-color:#209cee;border-color:transparent;-webkit-box-shadow:none;box-shadow:none}.button.is-info.is-inverted{background-color:#fff;color:#209cee}.button.is-info.is-inverted:hover{background-color:#f2f2f2}.button.is-info.is-inverted[disabled]{background-color:#fff;border-color:transparent;-webkit-box-shadow:none;box-shadow:none;color:#209cee}.button.is-info.is-loading:after{border-color:transparent transparent #fff #fff!important}.button.is-info.is-outlined{background-color:transparent;border-color:#209cee;color:#209cee}.button.is-info.is-outlined:focus,.button.is-info.is-outlined:hover{background-color:#209cee;border-color:#209cee;color:#fff}.button.is-info.is-outlined.is-loading:after{border-color:transparent transparent #209cee #209cee!important}.button.is-info.is-outlined[disabled]{background-color:transparent;border-color:#209cee;-webkit-box-shadow:none;box-shadow:none;color:#209cee}.button.is-info.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}.button.is-info.is-inverted.is-outlined:focus,.button.is-info.is-inverted.is-outlined:hover{background-color:#fff;color:#209cee}.button.is-info.is-inverted.is-outlined[disabled]{background-color:transparent;border-color:#fff;-webkit-box-shadow:none;box-shadow:none;color:#fff}.button.is-success{background-color:#23d160;border-color:transparent;color:#fff}.button.is-success.is-hovered,.button.is-success:hover{background-color:#22c65b;border-color:transparent;color:#fff}.button.is-success.is-focused,.button.is-success:focus{border-color:transparent;color:#fff}.button.is-success.is-focused:not(:active),.button.is-success:focus:not(:active){-webkit-box-shadow:0 0 0 .125em rgba(35,209,96,.25);box-shadow:0 0 0 .125em rgba(35,209,96,.25)}.button.is-success.is-active,.button.is-success:active{background-color:#20bc56;border-color:transparent;color:#fff}.button.is-success[disabled]{background-color:#23d160;border-color:transparent;-webkit-box-shadow:none;box-shadow:none}.button.is-success.is-inverted{background-color:#fff;color:#23d160}.button.is-success.is-inverted:hover{background-color:#f2f2f2}.button.is-success.is-inverted[disabled]{background-color:#fff;border-color:transparent;-webkit-box-shadow:none;box-shadow:none;color:#23d160}.button.is-success.is-loading:after{border-color:transparent transparent #fff #fff!important}.button.is-success.is-outlined{background-color:transparent;border-color:#23d160;color:#23d160}.button.is-success.is-outlined:focus,.button.is-success.is-outlined:hover{background-color:#23d160;border-color:#23d160;color:#fff}.button.is-success.is-outlined.is-loading:after{border-color:transparent transparent #23d160 #23d160!important}.button.is-success.is-outlined[disabled]{background-color:transparent;border-color:#23d160;-webkit-box-shadow:none;box-shadow:none;color:#23d160}.button.is-success.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}.button.is-success.is-inverted.is-outlined:focus,.button.is-success.is-inverted.is-outlined:hover{background-color:#fff;color:#23d160}.button.is-success.is-inverted.is-outlined[disabled]{background-color:transparent;border-color:#fff;-webkit-box-shadow:none;box-shadow:none;color:#fff}.button.is-warning{background-color:#ffdd57;border-color:transparent;color:rgba(0,0,0,.7)}.button.is-warning.is-hovered,.button.is-warning:hover{background-color:#ffdb4a;border-color:transparent;color:rgba(0,0,0,.7)}.button.is-warning.is-focused,.button.is-warning:focus{border-color:transparent;color:rgba(0,0,0,.7)}.button.is-warning.is-focused:not(:active),.button.is-warning:focus:not(:active){-webkit-box-shadow:0 0 0 .125em rgba(255,221,87,.25);box-shadow:0 0 0 .125em rgba(255,221,87,.25)}.button.is-warning.is-active,.button.is-warning:active{background-color:#ffd83d;border-color:transparent;color:rgba(0,0,0,.7)}.button.is-warning[disabled]{background-color:#ffdd57;border-color:transparent;-webkit-box-shadow:none;box-shadow:none}.button.is-warning.is-inverted{background-color:rgba(0,0,0,.7);color:#ffdd57}.button.is-warning.is-inverted:hover{background-color:rgba(0,0,0,.7)}.button.is-warning.is-inverted[disabled]{background-color:rgba(0,0,0,.7);border-color:transparent;-webkit-box-shadow:none;box-shadow:none;color:#ffdd57}.button.is-warning.is-loading:after{border-color:transparent transparent rgba(0,0,0,.7) rgba(0,0,0,.7)!important}.button.is-warning.is-outlined{background-color:transparent;border-color:#ffdd57;color:#ffdd57}.button.is-warning.is-outlined:focus,.button.is-warning.is-outlined:hover{background-color:#ffdd57;border-color:#ffdd57;color:rgba(0,0,0,.7)}.button.is-warning.is-outlined.is-loading:after{border-color:transparent transparent #ffdd57 #ffdd57!important}.button.is-warning.is-outlined[disabled]{background-color:transparent;border-color:#ffdd57;-webkit-box-shadow:none;box-shadow:none;color:#ffdd57}.button.is-warning.is-inverted.is-outlined{background-color:transparent;border-color:rgba(0,0,0,.7);color:rgba(0,0,0,.7)}.button.is-warning.is-inverted.is-outlined:focus,.button.is-warning.is-inverted.is-outlined:hover{background-color:rgba(0,0,0,.7);color:#ffdd57}.button.is-warning.is-inverted.is-outlined[disabled]{background-color:transparent;border-color:rgba(0,0,0,.7);-webkit-box-shadow:none;box-shadow:none;color:rgba(0,0,0,.7)}.button.is-danger{background-color:#ff3860;border-color:transparent;color:#fff}.button.is-danger.is-hovered,.button.is-danger:hover{background-color:#ff2b56;border-color:transparent;color:#fff}.button.is-danger.is-focused,.button.is-danger:focus{border-color:transparent;color:#fff}.button.is-danger.is-focused:not(:active),.button.is-danger:focus:not(:active){-webkit-box-shadow:0 0 0 .125em rgba(255,56,96,.25);box-shadow:0 0 0 .125em rgba(255,56,96,.25)}.button.is-danger.is-active,.button.is-danger:active{background-color:#ff1f4b;border-color:transparent;color:#fff}.button.is-danger[disabled]{background-color:#ff3860;border-color:transparent;-webkit-box-shadow:none;box-shadow:none}.button.is-danger.is-inverted{background-color:#fff;color:#ff3860}.button.is-danger.is-inverted:hover{background-color:#f2f2f2}.button.is-danger.is-inverted[disabled]{background-color:#fff;border-color:transparent;-webkit-box-shadow:none;box-shadow:none;color:#ff3860}.button.is-danger.is-loading:after{border-color:transparent transparent #fff #fff!important}.button.is-danger.is-outlined{background-color:transparent;border-color:#ff3860;color:#ff3860}.button.is-danger.is-outlined:focus,.button.is-danger.is-outlined:hover{background-color:#ff3860;border-color:#ff3860;color:#fff}.button.is-danger.is-outlined.is-loading:after{border-color:transparent transparent #ff3860 #ff3860!important}.button.is-danger.is-outlined[disabled]{background-color:transparent;border-color:#ff3860;-webkit-box-shadow:none;box-shadow:none;color:#ff3860}.button.is-danger.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}.button.is-danger.is-inverted.is-outlined:focus,.button.is-danger.is-inverted.is-outlined:hover{background-color:#fff;color:#ff3860}.button.is-danger.is-inverted.is-outlined[disabled]{background-color:transparent;border-color:#fff;-webkit-box-shadow:none;box-shadow:none;color:#fff}.button.is-small{border-radius:2px;font-size:.75rem}.button.is-medium{font-size:1.25rem}.button.is-large{font-size:1.5rem}.button[disabled]{background-color:#fff;border-color:#dbdbdb;-webkit-box-shadow:none;box-shadow:none;opacity:.5}.button.is-fullwidth{display:-webkit-box;display:-ms-flexbox;display:flex;width:100%}.button.is-loading{color:transparent!important;pointer-events:none}.button.is-loading:after{-webkit-animation:spinAround .5s infinite linear;animation:spinAround .5s infinite linear;border:2px solid #dbdbdb;border-radius:290486px;border-right-color:transparent;border-top-color:transparent;content:"";display:block;height:1em;position:relative;width:1em;position:absolute;left:calc(50% - (1em / 2));top:calc(50% - (1em / 2));position:absolute!important}.button.is-static{background-color:#f5f5f5;border-color:#dbdbdb;color:#7a7a7a;-webkit-box-shadow:none;box-shadow:none;pointer-events:none}.button.is-rounded{border-radius:290486px;padding-left:1em;padding-right:1em}.buttons{-webkit-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-box-pack:start;-ms-flex-pack:start;justify-content:flex-start}.buttons .button{margin-bottom:.5rem}.buttons .button:not(:last-child){margin-right:.5rem}.buttons:last-child{margin-bottom:-.5rem}.buttons:not(:last-child){margin-bottom:1rem}.buttons.has-addons .button:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.buttons.has-addons .button:not(:last-child){border-bottom-right-radius:0;border-top-right-radius:0;margin-right:-1px}.buttons.has-addons .button:last-child{margin-right:0}.buttons.has-addons .button.is-hovered,.buttons.has-addons .button:hover{z-index:2}.buttons.has-addons .button.is-active,.buttons.has-addons .button.is-focused,.buttons.has-addons .button.is-selected,.buttons.has-addons .button:active,.buttons.has-addons .button:focus{z-index:3}.buttons.has-addons .button.is-active:hover,.buttons.has-addons .button.is-focused:hover,.buttons.has-addons .button.is-selected:hover,.buttons.has-addons .button:active:hover,.buttons.has-addons .button:focus:hover{z-index:4}.buttons.is-centered{-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center}.buttons.is-right{-webkit-box-pack:end;-ms-flex-pack:end;justify-content:flex-end}.container{margin:0 auto;position:relative}@media screen and (min-width:1024px){.container{max-width:960px;width:960px}.container.is-fluid{margin-left:32px;margin-right:32px;max-width:none;width:auto}}@media screen and (max-width:1215px){.container.is-widescreen{max-width:1152px;width:auto}}@media screen and (max-width:1407px){.container.is-fullhd{max-width:1344px;width:auto}}@media screen and (min-width:1216px){.container{max-width:1152px;width:1152px}}@media screen and (min-width:1408px){.container{max-width:1344px;width:1344px}}.content:not(:last-child){margin-bottom:1.5rem}.content li+li{margin-top:.25em}.content blockquote:not(:last-child),.content dl:not(:last-child),.content ol:not(:last-child),.content p:not(:last-child),.content pre:not(:last-child),.content table:not(:last-child),.content ul:not(:last-child){margin-bottom:1em}.content h1,.content h2,.content h3,.content h4,.content h5,.content h6{color:#363636;font-weight:400;line-height:1.125}.content h1{font-size:2em;margin-bottom:.5em}.content h1:not(:first-child){margin-top:1em}.content h2{font-size:1.75em;margin-bottom:.5714em}.content h2:not(:first-child){margin-top:1.1428em}.content h3{font-size:1.5em;margin-bottom:.6666em}.content h3:not(:first-child){margin-top:1.3333em}.content h4{font-size:1.25em;margin-bottom:.8em}.content h5{font-size:1.125em;margin-bottom:.8888em}.content h6{font-size:1em;margin-bottom:1em}.content blockquote{background-color:#f5f5f5;border-left:5px solid #dbdbdb;padding:1.25em 1.5em}.content ol{list-style:decimal outside;margin-left:2em;margin-top:1em}.content ul{list-style:disc outside;margin-left:2em;margin-top:1em}.content ul ul{list-style-type:circle;margin-top:.5em}.content ul ul ul{list-style-type:square}.content dd{margin-left:2em}.content figure{margin-left:2em;margin-right:2em;text-align:center}.content figure:not(:first-child){margin-top:2em}.content figure:not(:last-child){margin-bottom:2em}.content figure img{display:inline-block}.content figure figcaption{font-style:italic}.content pre{-webkit-overflow-scrolling:touch;overflow-x:auto;padding:1.25em 1.5em;white-space:pre;word-wrap:normal}.content sub,.content sup{font-size:75%}.content table{width:100%}.content table td,.content table th{border:1px solid #dbdbdb;border-width:0 0 1px;padding:.5em .75em;vertical-align:top}.content table th{color:#363636;text-align:left}.content table tr:hover{background-color:#f5f5f5}.content table thead td,.content table thead th{border-width:0 0 2px;color:#363636}.content table tfoot td,.content table tfoot th{border-width:2px 0 0;color:#363636}.content table tbody tr:last-child td,.content table tbody tr:last-child th{border-bottom-width:0}.content.is-small{font-size:.75rem}.content.is-medium{font-size:1.25rem}.content.is-large{font-size:1.5rem}.input,.textarea{-moz-appearance:none;-webkit-appearance:none;-webkit-box-align:center;-ms-flex-align:center;align-items:center;border:1px solid transparent;border-radius:3px;-webkit-box-shadow:none;box-shadow:none;display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;font-size:1rem;height:2.25em;-webkit-box-pack:start;-ms-flex-pack:start;justify-content:flex-start;line-height:1.5;padding-bottom:calc(.375em - 1px);padding-left:calc(.625em - 1px);padding-right:calc(.625em - 1px);padding-top:calc(.375em - 1px);position:relative;vertical-align:top;background-color:#fff;border-color:#dbdbdb;color:#363636;-webkit-box-shadow:inset 0 1px 2px rgba(10,10,10,.1);box-shadow:inset 0 1px 2px rgba(10,10,10,.1);max-width:100%;width:100%}.input.is-active,.input.is-focused,.input:active,.input:focus,.textarea.is-active,.textarea.is-focused,.textarea:active,.textarea:focus{outline:0}.input[disabled],.textarea[disabled]{cursor:not-allowed}.input::-moz-placeholder,.textarea::-moz-placeholder{color:rgba(54,54,54,.3)}.input::-webkit-input-placeholder,.textarea::-webkit-input-placeholder{color:rgba(54,54,54,.3)}.input:-moz-placeholder,.textarea:-moz-placeholder{color:rgba(54,54,54,.3)}.input:-ms-input-placeholder,.textarea:-ms-input-placeholder{color:rgba(54,54,54,.3)}.input.is-hovered,.input:hover,.textarea.is-hovered,.textarea:hover{border-color:#b5b5b5}.input.is-active,.input.is-focused,.input:active,.input:focus,.textarea.is-active,.textarea.is-focused,.textarea:active,.textarea:focus{border-color:#3273dc;-webkit-box-shadow:0 0 0 .125em rgba(50,115,220,.25);box-shadow:0 0 0 .125em rgba(50,115,220,.25)}.input[disabled],.textarea[disabled]{background-color:#f5f5f5;border-color:#f5f5f5;-webkit-box-shadow:none;box-shadow:none;color:#7a7a7a}.input[disabled]::-moz-placeholder,.textarea[disabled]::-moz-placeholder{color:rgba(122,122,122,.3)}.input[disabled]::-webkit-input-placeholder,.textarea[disabled]::-webkit-input-placeholder{color:rgba(122,122,122,.3)}.input[disabled]:-moz-placeholder,.textarea[disabled]:-moz-placeholder{color:rgba(122,122,122,.3)}.input[disabled]:-ms-input-placeholder,.textarea[disabled]:-ms-input-placeholder{color:rgba(122,122,122,.3)}.input[readonly],.textarea[readonly]{-webkit-box-shadow:none;box-shadow:none}.input.is-white,.textarea.is-white{border-color:#fff}.input.is-white.is-active,.input.is-white.is-focused,.input.is-white:active,.input.is-white:focus,.textarea.is-white.is-active,.textarea.is-white.is-focused,.textarea.is-white:active,.textarea.is-white:focus{-webkit-box-shadow:0 0 0 .125em rgba(255,255,255,.25);box-shadow:0 0 0 .125em rgba(255,255,255,.25)}.input.is-black,.textarea.is-black{border-color:#0a0a0a}.input.is-black.is-active,.input.is-black.is-focused,.input.is-black:active,.input.is-black:focus,.textarea.is-black.is-active,.textarea.is-black.is-focused,.textarea.is-black:active,.textarea.is-black:focus{-webkit-box-shadow:0 0 0 .125em rgba(10,10,10,.25);box-shadow:0 0 0 .125em rgba(10,10,10,.25)}.input.is-light,.textarea.is-light{border-color:#f5f5f5}.input.is-light.is-active,.input.is-light.is-focused,.input.is-light:active,.input.is-light:focus,.textarea.is-light.is-active,.textarea.is-light.is-focused,.textarea.is-light:active,.textarea.is-light:focus{-webkit-box-shadow:0 0 0 .125em rgba(245,245,245,.25);box-shadow:0 0 0 .125em rgba(245,245,245,.25)}.input.is-dark,.textarea.is-dark{border-color:#363636}.input.is-dark.is-active,.input.is-dark.is-focused,.input.is-dark:active,.input.is-dark:focus,.textarea.is-dark.is-active,.textarea.is-dark.is-focused,.textarea.is-dark:active,.textarea.is-dark:focus{-webkit-box-shadow:0 0 0 .125em rgba(54,54,54,.25);box-shadow:0 0 0 .125em rgba(54,54,54,.25)}.input.is-primary,.textarea.is-primary{border-color:#00d1b2}.input.is-primary.is-active,.input.is-primary.is-focused,.input.is-primary:active,.input.is-primary:focus,.textarea.is-primary.is-active,.textarea.is-primary.is-focused,.textarea.is-primary:active,.textarea.is-primary:focus{-webkit-box-shadow:0 0 0 .125em rgba(0,209,178,.25);box-shadow:0 0 0 .125em rgba(0,209,178,.25)}.input.is-link,.textarea.is-link{border-color:#3273dc}.input.is-link.is-active,.input.is-link.is-focused,.input.is-link:active,.input.is-link:focus,.textarea.is-link.is-active,.textarea.is-link.is-focused,.textarea.is-link:active,.textarea.is-link:focus{-webkit-box-shadow:0 0 0 .125em rgba(50,115,220,.25);box-shadow:0 0 0 .125em rgba(50,115,220,.25)}.input.is-info,.textarea.is-info{border-color:#209cee}.input.is-info.is-active,.input.is-info.is-focused,.input.is-info:active,.input.is-info:focus,.textarea.is-info.is-active,.textarea.is-info.is-focused,.textarea.is-info:active,.textarea.is-info:focus{-webkit-box-shadow:0 0 0 .125em rgba(32,156,238,.25);box-shadow:0 0 0 .125em rgba(32,156,238,.25)}.input.is-success,.textarea.is-success{border-color:#23d160}.input.is-success.is-active,.input.is-success.is-focused,.input.is-success:active,.input.is-success:focus,.textarea.is-success.is-active,.textarea.is-success.is-focused,.textarea.is-success:active,.textarea.is-success:focus{-webkit-box-shadow:0 0 0 .125em rgba(35,209,96,.25);box-shadow:0 0 0 .125em rgba(35,209,96,.25)}.input.is-warning,.textarea.is-warning{border-color:#ffdd57}.input.is-warning.is-active,.input.is-warning.is-focused,.input.is-warning:active,.input.is-warning:focus,.textarea.is-warning.is-active,.textarea.is-warning.is-focused,.textarea.is-warning:active,.textarea.is-warning:focus{-webkit-box-shadow:0 0 0 .125em rgba(255,221,87,.25);box-shadow:0 0 0 .125em rgba(255,221,87,.25)}.input.is-danger,.textarea.is-danger{border-color:#ff3860}.input.is-danger.is-active,.input.is-danger.is-focused,.input.is-danger:active,.input.is-danger:focus,.textarea.is-danger.is-active,.textarea.is-danger.is-focused,.textarea.is-danger:active,.textarea.is-danger:focus{-webkit-box-shadow:0 0 0 .125em rgba(255,56,96,.25);box-shadow:0 0 0 .125em rgba(255,56,96,.25)}.input.is-small,.textarea.is-small{border-radius:2px;font-size:.75rem}.input.is-medium,.textarea.is-medium{font-size:1.25rem}.input.is-large,.textarea.is-large{font-size:1.5rem}.input.is-fullwidth,.textarea.is-fullwidth{display:block;width:100%}.input.is-inline,.textarea.is-inline{display:inline;width:auto}.input.is-rounded{border-radius:290486px;padding-left:1em;padding-right:1em}.input.is-static{background-color:transparent;border-color:transparent;-webkit-box-shadow:none;box-shadow:none;padding-left:0;padding-right:0}.textarea{display:block;max-width:100%;min-width:100%;padding:.625em;resize:vertical}.textarea:not([rows]){max-height:600px;min-height:120px}.textarea[rows]{height:unset}.textarea.has-fixed-size{resize:none}.checkbox,.radio{cursor:pointer;display:inline-block;line-height:1.25;position:relative}.checkbox input,.radio input{cursor:pointer}.checkbox:hover,.radio:hover{color:#363636}.checkbox[disabled],.radio[disabled]{color:#7a7a7a;cursor:not-allowed}.radio+.radio{margin-left:.5em}.select{display:inline-block;max-width:100%;position:relative;vertical-align:top}.select:not(.is-multiple){height:2.25em}.select:not(.is-multiple)::after{border:1px solid #3273dc;border-right:0;border-top:0;content:" ";display:block;height:.5em;pointer-events:none;position:absolute;-webkit-transform:rotate(-45deg);transform:rotate(-45deg);-webkit-transform-origin:center;transform-origin:center;width:.5em;margin-top:-.375em;right:1.125em;top:50%;z-index:4}.select.is-rounded select{border-radius:290486px;padding-left:1em}.select select{-moz-appearance:none;-webkit-appearance:none;-webkit-box-align:center;-ms-flex-align:center;align-items:center;border:1px solid transparent;border-radius:3px;-webkit-box-shadow:none;box-shadow:none;display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;font-size:1rem;height:2.25em;-webkit-box-pack:start;-ms-flex-pack:start;justify-content:flex-start;line-height:1.5;padding-bottom:calc(.375em - 1px);padding-left:calc(.625em - 1px);padding-right:calc(.625em - 1px);padding-top:calc(.375em - 1px);position:relative;vertical-align:top;background-color:#fff;border-color:#dbdbdb;color:#363636;cursor:pointer;display:block;font-size:1em;max-width:100%;outline:0}.select select.is-active,.select select.is-focused,.select select:active,.select select:focus{outline:0}.select select[disabled]{cursor:not-allowed}.select select::-moz-placeholder{color:rgba(54,54,54,.3)}.select select::-webkit-input-placeholder{color:rgba(54,54,54,.3)}.select select:-moz-placeholder{color:rgba(54,54,54,.3)}.select select:-ms-input-placeholder{color:rgba(54,54,54,.3)}.select select.is-hovered,.select select:hover{border-color:#b5b5b5}.select select.is-active,.select select.is-focused,.select select:active,.select select:focus{border-color:#3273dc;-webkit-box-shadow:0 0 0 .125em rgba(50,115,220,.25);box-shadow:0 0 0 .125em rgba(50,115,220,.25)}.select select[disabled]{background-color:#f5f5f5;border-color:#f5f5f5;-webkit-box-shadow:none;box-shadow:none;color:#7a7a7a}.select select[disabled]::-moz-placeholder{color:rgba(122,122,122,.3)}.select select[disabled]::-webkit-input-placeholder{color:rgba(122,122,122,.3)}.select select[disabled]:-moz-placeholder{color:rgba(122,122,122,.3)}.select select[disabled]:-ms-input-placeholder{color:rgba(122,122,122,.3)}.select select::-ms-expand{display:none}.select select[disabled]:hover{border-color:#f5f5f5}.select select:not([multiple]){padding-right:2.5em}.select select[multiple]{height:unset;padding:0}.select select[multiple] option{padding:.5em 1em}.select:hover::after{border-color:#363636}.select.is-white select{border-color:#fff}.select.is-white select.is-active,.select.is-white select.is-focused,.select.is-white select:active,.select.is-white select:focus{-webkit-box-shadow:0 0 0 .125em rgba(255,255,255,.25);box-shadow:0 0 0 .125em rgba(255,255,255,.25)}.select.is-black select{border-color:#0a0a0a}.select.is-black select.is-active,.select.is-black select.is-focused,.select.is-black select:active,.select.is-black select:focus{-webkit-box-shadow:0 0 0 .125em rgba(10,10,10,.25);box-shadow:0 0 0 .125em rgba(10,10,10,.25)}.select.is-light select{border-color:#f5f5f5}.select.is-light select.is-active,.select.is-light select.is-focused,.select.is-light select:active,.select.is-light select:focus{-webkit-box-shadow:0 0 0 .125em rgba(245,245,245,.25);box-shadow:0 0 0 .125em rgba(245,245,245,.25)}.select.is-dark select{border-color:#363636}.select.is-dark select.is-active,.select.is-dark select.is-focused,.select.is-dark select:active,.select.is-dark select:focus{-webkit-box-shadow:0 0 0 .125em rgba(54,54,54,.25);box-shadow:0 0 0 .125em rgba(54,54,54,.25)}.select.is-primary select{border-color:#00d1b2}.select.is-primary select.is-active,.select.is-primary select.is-focused,.select.is-primary select:active,.select.is-primary select:focus{-webkit-box-shadow:0 0 0 .125em rgba(0,209,178,.25);box-shadow:0 0 0 .125em rgba(0,209,178,.25)}.select.is-link select{border-color:#3273dc}.select.is-link select.is-active,.select.is-link select.is-focused,.select.is-link select:active,.select.is-link select:focus{-webkit-box-shadow:0 0 0 .125em rgba(50,115,220,.25);box-shadow:0 0 0 .125em rgba(50,115,220,.25)}.select.is-info select{border-color:#209cee}.select.is-info select.is-active,.select.is-info select.is-focused,.select.is-info select:active,.select.is-info select:focus{-webkit-box-shadow:0 0 0 .125em rgba(32,156,238,.25);box-shadow:0 0 0 .125em rgba(32,156,238,.25)}.select.is-success select{border-color:#23d160}.select.is-success select.is-active,.select.is-success select.is-focused,.select.is-success select:active,.select.is-success select:focus{-webkit-box-shadow:0 0 0 .125em rgba(35,209,96,.25);box-shadow:0 0 0 .125em rgba(35,209,96,.25)}.select.is-warning select{border-color:#ffdd57}.select.is-warning select.is-active,.select.is-warning select.is-focused,.select.is-warning select:active,.select.is-warning select:focus{-webkit-box-shadow:0 0 0 .125em rgba(255,221,87,.25);box-shadow:0 0 0 .125em rgba(255,221,87,.25)}.select.is-danger select{border-color:#ff3860}.select.is-danger select.is-active,.select.is-danger select.is-focused,.select.is-danger select:active,.select.is-danger select:focus{-webkit-box-shadow:0 0 0 .125em rgba(255,56,96,.25);box-shadow:0 0 0 .125em rgba(255,56,96,.25)}.select.is-small{border-radius:2px;font-size:.75rem}.select.is-medium{font-size:1.25rem}.select.is-large{font-size:1.5rem}.select.is-disabled::after{border-color:#7a7a7a}.select.is-fullwidth{width:100%}.select.is-fullwidth select{width:100%}.select.is-loading::after{-webkit-animation:spinAround .5s infinite linear;animation:spinAround .5s infinite linear;border:2px solid #dbdbdb;border-radius:290486px;border-right-color:transparent;border-top-color:transparent;content:"";display:block;height:1em;position:relative;width:1em;margin-top:0;position:absolute;right:.625em;top:.625em;-webkit-transform:none;transform:none}.select.is-loading.is-small:after{font-size:.75rem}.select.is-loading.is-medium:after{font-size:1.25rem}.select.is-loading.is-large:after{font-size:1.5rem}.file{-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-box-align:stretch;-ms-flex-align:stretch;align-items:stretch;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:start;-ms-flex-pack:start;justify-content:flex-start;position:relative}.file.is-white .file-cta{background-color:#fff;border-color:transparent;color:#0a0a0a}.file.is-white.is-hovered .file-cta,.file.is-white:hover .file-cta{background-color:#f9f9f9;border-color:transparent;color:#0a0a0a}.file.is-white.is-focused .file-cta,.file.is-white:focus .file-cta{border-color:transparent;-webkit-box-shadow:0 0 .5em rgba(255,255,255,.25);box-shadow:0 0 .5em rgba(255,255,255,.25);color:#0a0a0a}.file.is-white.is-active .file-cta,.file.is-white:active .file-cta{background-color:#f2f2f2;border-color:transparent;color:#0a0a0a}.file.is-black .file-cta{background-color:#0a0a0a;border-color:transparent;color:#fff}.file.is-black.is-hovered .file-cta,.file.is-black:hover .file-cta{background-color:#040404;border-color:transparent;color:#fff}.file.is-black.is-focused .file-cta,.file.is-black:focus .file-cta{border-color:transparent;-webkit-box-shadow:0 0 .5em rgba(10,10,10,.25);box-shadow:0 0 .5em rgba(10,10,10,.25);color:#fff}.file.is-black.is-active .file-cta,.file.is-black:active .file-cta{background-color:#000;border-color:transparent;color:#fff}.file.is-light .file-cta{background-color:#f5f5f5;border-color:transparent;color:#363636}.file.is-light.is-hovered .file-cta,.file.is-light:hover .file-cta{background-color:#eee;border-color:transparent;color:#363636}.file.is-light.is-focused .file-cta,.file.is-light:focus .file-cta{border-color:transparent;-webkit-box-shadow:0 0 .5em rgba(245,245,245,.25);box-shadow:0 0 .5em rgba(245,245,245,.25);color:#363636}.file.is-light.is-active .file-cta,.file.is-light:active .file-cta{background-color:#e8e8e8;border-color:transparent;color:#363636}.file.is-dark .file-cta{background-color:#363636;border-color:transparent;color:#f5f5f5}.file.is-dark.is-hovered .file-cta,.file.is-dark:hover .file-cta{background-color:#2f2f2f;border-color:transparent;color:#f5f5f5}.file.is-dark.is-focused .file-cta,.file.is-dark:focus .file-cta{border-color:transparent;-webkit-box-shadow:0 0 .5em rgba(54,54,54,.25);box-shadow:0 0 .5em rgba(54,54,54,.25);color:#f5f5f5}.file.is-dark.is-active .file-cta,.file.is-dark:active .file-cta{background-color:#292929;border-color:transparent;color:#f5f5f5}.file.is-primary .file-cta{background-color:#00d1b2;border-color:transparent;color:#fff}.file.is-primary.is-hovered .file-cta,.file.is-primary:hover .file-cta{background-color:#00c4a7;border-color:transparent;color:#fff}.file.is-primary.is-focused .file-cta,.file.is-primary:focus .file-cta{border-color:transparent;-webkit-box-shadow:0 0 .5em rgba(0,209,178,.25);box-shadow:0 0 .5em rgba(0,209,178,.25);color:#fff}.file.is-primary.is-active .file-cta,.file.is-primary:active .file-cta{background-color:#00b89c;border-color:transparent;color:#fff}.file.is-link .file-cta{background-color:#3273dc;border-color:transparent;color:#fff}.file.is-link.is-hovered .file-cta,.file.is-link:hover .file-cta{background-color:#276cda;border-color:transparent;color:#fff}.file.is-link.is-focused .file-cta,.file.is-link:focus .file-cta{border-color:transparent;-webkit-box-shadow:0 0 .5em rgba(50,115,220,.25);box-shadow:0 0 .5em rgba(50,115,220,.25);color:#fff}.file.is-link.is-active .file-cta,.file.is-link:active .file-cta{background-color:#2366d1;border-color:transparent;color:#fff}.file.is-info .file-cta{background-color:#209cee;border-color:transparent;color:#fff}.file.is-info.is-hovered .file-cta,.file.is-info:hover .file-cta{background-color:#1496ed;border-color:transparent;color:#fff}.file.is-info.is-focused .file-cta,.file.is-info:focus .file-cta{border-color:transparent;-webkit-box-shadow:0 0 .5em rgba(32,156,238,.25);box-shadow:0 0 .5em rgba(32,156,238,.25);color:#fff}.file.is-info.is-active .file-cta,.file.is-info:active .file-cta{background-color:#118fe4;border-color:transparent;color:#fff}.file.is-success .file-cta{background-color:#23d160;border-color:transparent;color:#fff}.file.is-success.is-hovered .file-cta,.file.is-success:hover .file-cta{background-color:#22c65b;border-color:transparent;color:#fff}.file.is-success.is-focused .file-cta,.file.is-success:focus .file-cta{border-color:transparent;-webkit-box-shadow:0 0 .5em rgba(35,209,96,.25);box-shadow:0 0 .5em rgba(35,209,96,.25);color:#fff}.file.is-success.is-active .file-cta,.file.is-success:active .file-cta{background-color:#20bc56;border-color:transparent;color:#fff}.file.is-warning .file-cta{background-color:#ffdd57;border-color:transparent;color:rgba(0,0,0,.7)}.file.is-warning.is-hovered .file-cta,.file.is-warning:hover .file-cta{background-color:#ffdb4a;border-color:transparent;color:rgba(0,0,0,.7)}.file.is-warning.is-focused .file-cta,.file.is-warning:focus .file-cta{border-color:transparent;-webkit-box-shadow:0 0 .5em rgba(255,221,87,.25);box-shadow:0 0 .5em rgba(255,221,87,.25);color:rgba(0,0,0,.7)}.file.is-warning.is-active .file-cta,.file.is-warning:active .file-cta{background-color:#ffd83d;border-color:transparent;color:rgba(0,0,0,.7)}.file.is-danger .file-cta{background-color:#ff3860;border-color:transparent;color:#fff}.file.is-danger.is-hovered .file-cta,.file.is-danger:hover .file-cta{background-color:#ff2b56;border-color:transparent;color:#fff}.file.is-danger.is-focused .file-cta,.file.is-danger:focus .file-cta{border-color:transparent;-webkit-box-shadow:0 0 .5em rgba(255,56,96,.25);box-shadow:0 0 .5em rgba(255,56,96,.25);color:#fff}.file.is-danger.is-active .file-cta,.file.is-danger:active .file-cta{background-color:#ff1f4b;border-color:transparent;color:#fff}.file.is-small{font-size:.75rem}.file.is-medium{font-size:1.25rem}.file.is-medium .file-icon .fa{font-size:21px}.file.is-large{font-size:1.5rem}.file.is-large .file-icon .fa{font-size:28px}.file.has-name .file-cta{border-bottom-right-radius:0;border-top-right-radius:0}.file.has-name .file-name{border-bottom-left-radius:0;border-top-left-radius:0}.file.has-name.is-empty .file-cta{border-radius:3px}.file.has-name.is-empty .file-name{display:none}.file.is-boxed .file-label{-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column}.file.is-boxed .file-cta{-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;height:auto;padding:1em 3em}.file.is-boxed .file-name{border-width:0 1px 1px}.file.is-boxed .file-icon{height:1.5em;width:1.5em}.file.is-boxed .file-icon .fa{font-size:21px}.file.is-boxed.is-small .file-icon .fa{font-size:14px}.file.is-boxed.is-medium .file-icon .fa{font-size:28px}.file.is-boxed.is-large .file-icon .fa{font-size:35px}.file.is-boxed.has-name .file-cta{border-radius:3px 3px 0 0}.file.is-boxed.has-name .file-name{border-radius:0 0 3px 3px;border-width:0 1px 1px}.file.is-centered{-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center}.file.is-fullwidth .file-label{width:100%}.file.is-fullwidth .file-name{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;max-width:none}.file.is-right{-webkit-box-pack:end;-ms-flex-pack:end;justify-content:flex-end}.file.is-right .file-cta{border-radius:0 3px 3px 0}.file.is-right .file-name{border-radius:3px 0 0 3px;border-width:1px 0 1px 1px;-webkit-box-ordinal-group:0;-ms-flex-order:-1;order:-1}.file-label{-webkit-box-align:stretch;-ms-flex-align:stretch;align-items:stretch;display:-webkit-box;display:-ms-flexbox;display:flex;cursor:pointer;-webkit-box-pack:start;-ms-flex-pack:start;justify-content:flex-start;overflow:hidden;position:relative}.file-label:hover .file-cta{background-color:#eee;color:#363636}.file-label:hover .file-name{border-color:#d5d5d5}.file-label:active .file-cta{background-color:#e8e8e8;color:#363636}.file-label:active .file-name{border-color:#cfcfcf}.file-input{height:.01em;left:0;outline:0;position:absolute;top:0;width:.01em}.file-cta,.file-name{-moz-appearance:none;-webkit-appearance:none;-webkit-box-align:center;-ms-flex-align:center;align-items:center;border:1px solid transparent;border-radius:3px;-webkit-box-shadow:none;box-shadow:none;display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;font-size:1rem;height:2.25em;-webkit-box-pack:start;-ms-flex-pack:start;justify-content:flex-start;line-height:1.5;padding-bottom:calc(.375em - 1px);padding-left:calc(.625em - 1px);padding-right:calc(.625em - 1px);padding-top:calc(.375em - 1px);position:relative;vertical-align:top;border-color:#dbdbdb;border-radius:3px;font-size:1em;padding-left:1em;padding-right:1em;white-space:nowrap}.file-cta.is-active,.file-cta.is-focused,.file-cta:active,.file-cta:focus,.file-name.is-active,.file-name.is-focused,.file-name:active,.file-name:focus{outline:0}.file-cta[disabled],.file-name[disabled]{cursor:not-allowed}.file-cta{background-color:#f5f5f5;color:#4a4a4a}.file-name{border-color:#dbdbdb;border-style:solid;border-width:1px 1px 1px 0;display:block;max-width:16em;overflow:hidden;text-align:left;text-overflow:ellipsis}.file-icon{-webkit-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-ms-flexbox;display:flex;height:1em;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;margin-right:.5em;width:1em}.file-icon .fa{font-size:14px}.label{color:#363636;display:block;font-size:1rem;font-weight:700}.label:not(:last-child){margin-bottom:.5em}.label.is-small{font-size:.75rem}.label.is-medium{font-size:1.25rem}.label.is-large{font-size:1.5rem}.help{display:block;font-size:.75rem;margin-top:.25rem}.help.is-white{color:#fff}.help.is-black{color:#0a0a0a}.help.is-light{color:#f5f5f5}.help.is-dark{color:#363636}.help.is-primary{color:#00d1b2}.help.is-link{color:#3273dc}.help.is-info{color:#209cee}.help.is-success{color:#23d160}.help.is-warning{color:#ffdd57}.help.is-danger{color:#ff3860}.field:not(:last-child){margin-bottom:.75rem}.field.has-addons{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:start;-ms-flex-pack:start;justify-content:flex-start}.field.has-addons .control:not(:last-child){margin-right:-1px}.field.has-addons .control:not(:first-child):not(:last-child) .button,.field.has-addons .control:not(:first-child):not(:last-child) .input,.field.has-addons .control:not(:first-child):not(:last-child) .select select{border-radius:0}.field.has-addons .control:first-child .button,.field.has-addons .control:first-child .input,.field.has-addons .control:first-child .select select{border-bottom-right-radius:0;border-top-right-radius:0}.field.has-addons .control:last-child .button,.field.has-addons .control:last-child .input,.field.has-addons .control:last-child .select select{border-bottom-left-radius:0;border-top-left-radius:0}.field.has-addons .control .button.is-hovered,.field.has-addons .control .button:hover,.field.has-addons .control .input.is-hovered,.field.has-addons .control .input:hover,.field.has-addons .control .select select.is-hovered,.field.has-addons .control .select select:hover{z-index:2}.field.has-addons .control .button.is-active,.field.has-addons .control .button.is-focused,.field.has-addons .control .button:active,.field.has-addons .control .button:focus,.field.has-addons .control .input.is-active,.field.has-addons .control .input.is-focused,.field.has-addons .control .input:active,.field.has-addons .control .input:focus,.field.has-addons .control .select select.is-active,.field.has-addons .control .select select.is-focused,.field.has-addons .control .select select:active,.field.has-addons .control .select select:focus{z-index:3}.field.has-addons .control .button.is-active:hover,.field.has-addons .control .button.is-focused:hover,.field.has-addons .control .button:active:hover,.field.has-addons .control .button:focus:hover,.field.has-addons .control .input.is-active:hover,.field.has-addons .control .input.is-focused:hover,.field.has-addons .control .input:active:hover,.field.has-addons .control .input:focus:hover,.field.has-addons .control .select select.is-active:hover,.field.has-addons .control .select select.is-focused:hover,.field.has-addons .control .select select:active:hover,.field.has-addons .control .select select:focus:hover{z-index:4}.field.has-addons .control.is-expanded{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1}.field.has-addons.has-addons-centered{-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center}.field.has-addons.has-addons-right{-webkit-box-pack:end;-ms-flex-pack:end;justify-content:flex-end}.field.has-addons.has-addons-fullwidth .control{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;-ms-flex-negative:0;flex-shrink:0}.field.is-grouped{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:start;-ms-flex-pack:start;justify-content:flex-start}.field.is-grouped>.control{-ms-flex-negative:0;flex-shrink:0}.field.is-grouped>.control:not(:last-child){margin-bottom:0;margin-right:.75rem}.field.is-grouped>.control.is-expanded{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;-ms-flex-negative:1;flex-shrink:1}.field.is-grouped.is-grouped-centered{-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center}.field.is-grouped.is-grouped-right{-webkit-box-pack:end;-ms-flex-pack:end;justify-content:flex-end}.field.is-grouped.is-grouped-multiline{-ms-flex-wrap:wrap;flex-wrap:wrap}.field.is-grouped.is-grouped-multiline>.control:last-child,.field.is-grouped.is-grouped-multiline>.control:not(:last-child){margin-bottom:.75rem}.field.is-grouped.is-grouped-multiline:last-child{margin-bottom:-.75rem}.field.is-grouped.is-grouped-multiline:not(:last-child){margin-bottom:0}@media screen and (min-width:769px),print{.field.is-horizontal{display:-webkit-box;display:-ms-flexbox;display:flex}}.field-label .label{font-size:inherit}@media screen and (max-width:768px){.field-label{margin-bottom:.5rem}}@media screen and (min-width:769px),print{.field-label{-ms-flex-preferred-size:0;flex-basis:0;-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;-ms-flex-negative:0;flex-shrink:0;margin-right:1.5rem;text-align:right}.field-label.is-small{font-size:.75rem;padding-top:.375em}.field-label.is-normal{padding-top:.375em}.field-label.is-medium{font-size:1.25rem;padding-top:.375em}.field-label.is-large{font-size:1.5rem;padding-top:.375em}}.field-body .field .field{margin-bottom:0}@media screen and (min-width:769px),print{.field-body{display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-preferred-size:0;flex-basis:0;-webkit-box-flex:5;-ms-flex-positive:5;flex-grow:5;-ms-flex-negative:1;flex-shrink:1}.field-body .field{margin-bottom:0}.field-body>.field{-ms-flex-negative:1;flex-shrink:1}.field-body>.field:not(.is-narrow){-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1}.field-body>.field:not(:last-child){margin-right:.75rem}}.control{font-size:1rem;position:relative;text-align:left}.control.has-icon .icon{color:#dbdbdb;height:2.25em;pointer-events:none;position:absolute;top:0;width:2.25em;z-index:4}.control.has-icon .input:focus+.icon{color:#7a7a7a}.control.has-icon .input.is-small+.icon{font-size:.75rem}.control.has-icon .input.is-medium+.icon{font-size:1.25rem}.control.has-icon .input.is-large+.icon{font-size:1.5rem}.control.has-icon:not(.has-icon-right) .icon{left:0}.control.has-icon:not(.has-icon-right) .input{padding-left:2.25em}.control.has-icon.has-icon-right .icon{right:0}.control.has-icon.has-icon-right .input{padding-right:2.25em}.control.has-icons-left .input:focus~.icon,.control.has-icons-left .select:focus~.icon,.control.has-icons-right .input:focus~.icon,.control.has-icons-right .select:focus~.icon{color:#7a7a7a}.control.has-icons-left .input.is-small~.icon,.control.has-icons-left .select.is-small~.icon,.control.has-icons-right .input.is-small~.icon,.control.has-icons-right .select.is-small~.icon{font-size:.75rem}.control.has-icons-left .input.is-medium~.icon,.control.has-icons-left .select.is-medium~.icon,.control.has-icons-right .input.is-medium~.icon,.control.has-icons-right .select.is-medium~.icon{font-size:1.25rem}.control.has-icons-left .input.is-large~.icon,.control.has-icons-left .select.is-large~.icon,.control.has-icons-right .input.is-large~.icon,.control.has-icons-right .select.is-large~.icon{font-size:1.5rem}.control.has-icons-left .icon,.control.has-icons-right .icon{color:#dbdbdb;height:2.25em;pointer-events:none;position:absolute;top:0;width:2.25em;z-index:4}.control.has-icons-left .input,.control.has-icons-left .select select{padding-left:2.25em}.control.has-icons-left .icon.is-left{left:0}.control.has-icons-right .input,.control.has-icons-right .select select{padding-right:2.25em}.control.has-icons-right .icon.is-right{right:0}.control.is-loading::after{-webkit-animation:spinAround .5s infinite linear;animation:spinAround .5s infinite linear;border:2px solid #dbdbdb;border-radius:290486px;border-right-color:transparent;border-top-color:transparent;content:"";display:block;height:1em;position:relative;width:1em;position:absolute!important;right:.625em;top:.625em;z-index:4}.control.is-loading.is-small:after{font-size:.75rem}.control.is-loading.is-medium:after{font-size:1.25rem}.control.is-loading.is-large:after{font-size:1.5rem}.icon{-webkit-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;height:1.5rem;width:1.5rem}.icon.is-small{height:1rem;width:1rem}.icon.is-medium{height:2rem;width:2rem}.icon.is-large{height:3rem;width:3rem}.image{display:block;position:relative}.image img{display:block;height:auto;width:100%}.image img.is-rounded{border-radius:290486px}.image.is-16by9 img,.image.is-1by1 img,.image.is-2by1 img,.image.is-3by2 img,.image.is-4by3 img,.image.is-square img{bottom:0;left:0;position:absolute;right:0;top:0;height:100%;width:100%}.image.is-1by1,.image.is-square{padding-top:100%}.image.is-4by3{padding-top:75%}.image.is-3by2{padding-top:66.6666%}.image.is-16by9{padding-top:56.25%}.image.is-2by1{padding-top:50%}.image.is-16x16{height:16px;width:16px}.image.is-24x24{height:24px;width:24px}.image.is-32x32{height:32px;width:32px}.image.is-48x48{height:48px;width:48px}.image.is-64x64{height:64px;width:64px}.image.is-96x96{height:96px;width:96px}.image.is-128x128{height:128px;width:128px}.notification{background-color:#f5f5f5;border-radius:3px;padding:1.25rem 2.5rem 1.25rem 1.5rem;position:relative}.notification:not(:last-child){margin-bottom:1.5rem}.notification a:not(.button){color:currentColor;text-decoration:underline}.notification strong{color:currentColor}.notification code,.notification pre{background:#fff}.notification pre code{background:0 0}.notification>.delete{position:absolute;right:.5rem;top:.5rem}.notification .content,.notification .subtitle,.notification .title{color:currentColor}.notification.is-white{background-color:#fff;color:#0a0a0a}.notification.is-black{background-color:#0a0a0a;color:#fff}.notification.is-light{background-color:#f5f5f5;color:#363636}.notification.is-dark{background-color:#363636;color:#f5f5f5}.notification.is-primary{background-color:#00d1b2;color:#fff}.notification.is-link{background-color:#3273dc;color:#fff}.notification.is-info{background-color:#209cee;color:#fff}.notification.is-success{background-color:#23d160;color:#fff}.notification.is-warning{background-color:#ffdd57;color:rgba(0,0,0,.7)}.notification.is-danger{background-color:#ff3860;color:#fff}.progress{-moz-appearance:none;-webkit-appearance:none;border:none;border-radius:290486px;display:block;height:1rem;overflow:hidden;padding:0;width:100%}.progress:not(:last-child){margin-bottom:1.5rem}.progress::-webkit-progress-bar{background-color:#dbdbdb}.progress::-webkit-progress-value{background-color:#4a4a4a}.progress::-moz-progress-bar{background-color:#4a4a4a}.progress::-ms-fill{background-color:#4a4a4a;border:none}.progress.is-white::-webkit-progress-value{background-color:#fff}.progress.is-white::-moz-progress-bar{background-color:#fff}.progress.is-white::-ms-fill{background-color:#fff}.progress.is-black::-webkit-progress-value{background-color:#0a0a0a}.progress.is-black::-moz-progress-bar{background-color:#0a0a0a}.progress.is-black::-ms-fill{background-color:#0a0a0a}.progress.is-light::-webkit-progress-value{background-color:#f5f5f5}.progress.is-light::-moz-progress-bar{background-color:#f5f5f5}.progress.is-light::-ms-fill{background-color:#f5f5f5}.progress.is-dark::-webkit-progress-value{background-color:#363636}.progress.is-dark::-moz-progress-bar{background-color:#363636}.progress.is-dark::-ms-fill{background-color:#363636}.progress.is-primary::-webkit-progress-value{background-color:#00d1b2}.progress.is-primary::-moz-progress-bar{background-color:#00d1b2}.progress.is-primary::-ms-fill{background-color:#00d1b2}.progress.is-link::-webkit-progress-value{background-color:#3273dc}.progress.is-link::-moz-progress-bar{background-color:#3273dc}.progress.is-link::-ms-fill{background-color:#3273dc}.progress.is-info::-webkit-progress-value{background-color:#209cee}.progress.is-info::-moz-progress-bar{background-color:#209cee}.progress.is-info::-ms-fill{background-color:#209cee}.progress.is-success::-webkit-progress-value{background-color:#23d160}.progress.is-success::-moz-progress-bar{background-color:#23d160}.progress.is-success::-ms-fill{background-color:#23d160}.progress.is-warning::-webkit-progress-value{background-color:#ffdd57}.progress.is-warning::-moz-progress-bar{background-color:#ffdd57}.progress.is-warning::-ms-fill{background-color:#ffdd57}.progress.is-danger::-webkit-progress-value{background-color:#ff3860}.progress.is-danger::-moz-progress-bar{background-color:#ff3860}.progress.is-danger::-ms-fill{background-color:#ff3860}.progress.is-small{height:.75rem}.progress.is-medium{height:1.25rem}.progress.is-large{height:1.5rem}.table{background-color:#fff;color:#363636;margin-bottom:1.5rem}.table td,.table th{border:1px solid #dbdbdb;border-width:0 0 1px;padding:.5em .75em;vertical-align:top}.table td.is-white,.table th.is-white{background-color:#fff;border-color:#fff;color:#0a0a0a}.table td.is-black,.table th.is-black{background-color:#0a0a0a;border-color:#0a0a0a;color:#fff}.table td.is-light,.table th.is-light{background-color:#f5f5f5;border-color:#f5f5f5;color:#363636}.table td.is-dark,.table th.is-dark{background-color:#363636;border-color:#363636;color:#f5f5f5}.table td.is-primary,.table th.is-primary{background-color:#00d1b2;border-color:#00d1b2;color:#fff}.table td.is-link,.table th.is-link{background-color:#3273dc;border-color:#3273dc;color:#fff}.table td.is-info,.table th.is-info{background-color:#209cee;border-color:#209cee;color:#fff}.table td.is-success,.table th.is-success{background-color:#23d160;border-color:#23d160;color:#fff}.table td.is-warning,.table th.is-warning{background-color:#ffdd57;border-color:#ffdd57;color:rgba(0,0,0,.7)}.table td.is-danger,.table th.is-danger{background-color:#ff3860;border-color:#ff3860;color:#fff}.table td.is-narrow,.table th.is-narrow{white-space:nowrap;width:1%}.table td.is-selected,.table th.is-selected{background-color:#00d1b2;color:#fff}.table td.is-selected a,.table td.is-selected strong,.table th.is-selected a,.table th.is-selected strong{color:currentColor}.table th{color:#363636;text-align:left}.table tr.is-selected{background-color:#00d1b2;color:#fff}.table tr.is-selected a,.table tr.is-selected strong{color:currentColor}.table tr.is-selected td,.table tr.is-selected th{border-color:#fff;color:currentColor}.table thead td,.table thead th{border-width:0 0 2px;color:#363636}.table tfoot td,.table tfoot th{border-width:2px 0 0;color:#363636}.table tbody tr:last-child td,.table tbody tr:last-child th{border-bottom-width:0}.table.is-bordered td,.table.is-bordered th{border-width:1px}.table.is-bordered tr:last-child td,.table.is-bordered tr:last-child th{border-bottom-width:1px}.table.is-fullwidth{width:100%}.table.is-hoverable tbody tr:not(.is-selected):hover{background-color:#fafafa}.table.is-hoverable.is-striped tbody tr:not(.is-selected):hover{background-color:#f5f5f5}.table.is-narrow td,.table.is-narrow th{padding:.25em .5em}.table.is-striped tbody tr:not(.is-selected):nth-child(even){background-color:#fafafa}.tags{-webkit-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-box-pack:start;-ms-flex-pack:start;justify-content:flex-start}.tags .tag{margin-bottom:.5rem}.tags .tag:not(:last-child){margin-right:.5rem}.tags:last-child{margin-bottom:-.5rem}.tags:not(:last-child){margin-bottom:1rem}.tags.has-addons .tag{margin-right:0}.tags.has-addons .tag:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.tags.has-addons .tag:not(:last-child){border-bottom-right-radius:0;border-top-right-radius:0}.tags.is-centered{-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center}.tags.is-centered .tag{margin-right:.25rem;margin-left:.25rem}.tags.is-right{-webkit-box-pack:end;-ms-flex-pack:end;justify-content:flex-end}.tags.is-right .tag:not(:first-child){margin-left:.5rem}.tags.is-right .tag:not(:last-child){margin-right:0}.tag:not(body){-webkit-box-align:center;-ms-flex-align:center;align-items:center;background-color:#f5f5f5;border-radius:3px;color:#4a4a4a;display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;font-size:.75rem;height:2em;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;line-height:1.5;padding-left:.75em;padding-right:.75em;white-space:nowrap}.tag:not(body) .delete{margin-left:.25em;margin-right:-.375em}.tag:not(body).is-white{background-color:#fff;color:#0a0a0a}.tag:not(body).is-black{background-color:#0a0a0a;color:#fff}.tag:not(body).is-light{background-color:#f5f5f5;color:#363636}.tag:not(body).is-dark{background-color:#363636;color:#f5f5f5}.tag:not(body).is-primary{background-color:#00d1b2;color:#fff}.tag:not(body).is-link{background-color:#3273dc;color:#fff}.tag:not(body).is-info{background-color:#209cee;color:#fff}.tag:not(body).is-success{background-color:#23d160;color:#fff}.tag:not(body).is-warning{background-color:#ffdd57;color:rgba(0,0,0,.7)}.tag:not(body).is-danger{background-color:#ff3860;color:#fff}.tag:not(body).is-medium{font-size:1rem}.tag:not(body).is-large{font-size:1.25rem}.tag:not(body) .icon:first-child:not(:last-child){margin-left:-.375em;margin-right:.1875em}.tag:not(body) .icon:last-child:not(:first-child){margin-left:.1875em;margin-right:-.375em}.tag:not(body) .icon:first-child:last-child{margin-left:-.375em;margin-right:-.375em}.tag:not(body).is-delete{margin-left:1px;padding:0;position:relative;width:2em}.tag:not(body).is-delete:after,.tag:not(body).is-delete:before{background-color:currentColor;content:"";display:block;left:50%;position:absolute;top:50%;-webkit-transform:translateX(-50%) translateY(-50%) rotate(45deg);transform:translateX(-50%) translateY(-50%) rotate(45deg);-webkit-transform-origin:center center;transform-origin:center center}.tag:not(body).is-delete:before{height:1px;width:50%}.tag:not(body).is-delete:after{height:50%;width:1px}.tag:not(body).is-delete:focus,.tag:not(body).is-delete:hover{background-color:#e8e8e8}.tag:not(body).is-delete:active{background-color:#dbdbdb}.tag:not(body).is-rounded{border-radius:290486px}a.tag:hover{text-decoration:underline}.subtitle,.title{word-break:break-word}.subtitle:not(:last-child),.title:not(:last-child){margin-bottom:1.5rem}.subtitle em,.subtitle span,.title em,.title span{font-weight:inherit}.subtitle sub,.title sub{font-size:.75em}.subtitle sup,.title sup{font-size:.75em}.subtitle .tag,.title .tag{vertical-align:middle}.title{color:#363636;font-size:2rem;font-weight:600;line-height:1.125}.title strong{color:inherit;font-weight:inherit}.title+.highlight{margin-top:-.75rem}.title:not(.is-spaced)+.subtitle{margin-top:-1.5rem}.title.is-1{font-size:3rem}.title.is-2{font-size:2.5rem}.title.is-3{font-size:2rem}.title.is-4{font-size:1.5rem}.title.is-5{font-size:1.25rem}.title.is-6{font-size:1rem}.title.is-7{font-size:.75rem}.subtitle{color:#4a4a4a;font-size:1.25rem;font-weight:400;line-height:1.25}.subtitle strong{color:#363636;font-weight:600}.subtitle:not(.is-spaced)+.title{margin-top:-1.5rem}.subtitle.is-1{font-size:3rem}.subtitle.is-2{font-size:2.5rem}.subtitle.is-3{font-size:2rem}.subtitle.is-4{font-size:1.5rem}.subtitle.is-5{font-size:1.25rem}.subtitle.is-6{font-size:1rem}.subtitle.is-7{font-size:.75rem}.block:not(:last-child){margin-bottom:1.5rem}.delete{-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-moz-appearance:none;-webkit-appearance:none;background-color:rgba(10,10,10,.2);border:none;border-radius:290486px;cursor:pointer;display:inline-block;-webkit-box-flex:0;-ms-flex-positive:0;flex-grow:0;-ms-flex-negative:0;flex-shrink:0;font-size:0;height:20px;max-height:20px;max-width:20px;min-height:20px;min-width:20px;outline:0;position:relative;vertical-align:top;width:20px}.delete:after,.delete:before{background-color:#fff;content:"";display:block;left:50%;position:absolute;top:50%;-webkit-transform:translateX(-50%) translateY(-50%) rotate(45deg);transform:translateX(-50%) translateY(-50%) rotate(45deg);-webkit-transform-origin:center center;transform-origin:center center}.delete:before{height:2px;width:50%}.delete:after{height:50%;width:2px}.delete:focus,.delete:hover{background-color:rgba(10,10,10,.3)}.delete:active{background-color:rgba(10,10,10,.4)}.delete.is-small{height:16px;max-height:16px;max-width:16px;min-height:16px;min-width:16px;width:16px}.delete.is-medium{height:24px;max-height:24px;max-width:24px;min-height:24px;min-width:24px;width:24px}.delete.is-large{height:32px;max-height:32px;max-width:32px;min-height:32px;min-width:32px;width:32px}.heading{display:block;font-size:11px;letter-spacing:1px;margin-bottom:5px;text-transform:uppercase}.highlight{font-weight:400;max-width:100%;overflow:hidden;padding:0}.highlight:not(:last-child){margin-bottom:1.5rem}.highlight pre{overflow:auto;max-width:100%}.loader{-webkit-animation:spinAround .5s infinite linear;animation:spinAround .5s infinite linear;border:2px solid #dbdbdb;border-radius:290486px;border-right-color:transparent;border-top-color:transparent;content:"";display:block;height:1em;position:relative;width:1em}.number{-webkit-box-align:center;-ms-flex-align:center;align-items:center;background-color:#f5f5f5;border-radius:290486px;display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;font-size:1.25rem;height:2em;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;margin-right:1.5rem;min-width:2.5em;padding:.25rem .5rem;text-align:center;vertical-align:top}.breadcrumb{-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-box-align:stretch;-ms-flex-align:stretch;align-items:stretch;display:-webkit-box;display:-ms-flexbox;display:flex;font-size:1rem;overflow:hidden;overflow-x:auto;white-space:nowrap}.breadcrumb:not(:last-child){margin-bottom:1.5rem}.breadcrumb a{-webkit-box-align:center;-ms-flex-align:center;align-items:center;color:#3273dc;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;padding:.5em .75em}.breadcrumb a:hover{color:#363636}.breadcrumb li{-webkit-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-ms-flexbox;display:flex}.breadcrumb li:first-child a{padding-left:0}.breadcrumb li.is-active a{color:#363636;cursor:default;pointer-events:none}.breadcrumb li+li::before{color:#4a4a4a;content:"\0002f"}.breadcrumb ol,.breadcrumb ul{-webkit-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;-ms-flex-negative:0;flex-shrink:0;-webkit-box-pack:start;-ms-flex-pack:start;justify-content:flex-start}.breadcrumb .icon:first-child{margin-right:.5em}.breadcrumb .icon:last-child{margin-left:.5em}.breadcrumb.is-centered ol,.breadcrumb.is-centered ul{-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center}.breadcrumb.is-right ol,.breadcrumb.is-right ul{-webkit-box-pack:end;-ms-flex-pack:end;justify-content:flex-end}.breadcrumb.is-small{font-size:.75rem}.breadcrumb.is-medium{font-size:1.25rem}.breadcrumb.is-large{font-size:1.5rem}.breadcrumb.has-arrow-separator li+li::before{content:"\02192"}.breadcrumb.has-bullet-separator li+li::before{content:"\02022"}.breadcrumb.has-dot-separator li+li::before{content:"\000b7"}.breadcrumb.has-succeeds-separator li+li::before{content:"\0227B"}.card{background-color:#fff;-webkit-box-shadow:0 2px 3px rgba(10,10,10,.1),0 0 0 1px rgba(10,10,10,.1);box-shadow:0 2px 3px rgba(10,10,10,.1),0 0 0 1px rgba(10,10,10,.1);color:#4a4a4a;max-width:100%;position:relative}.card-header{-webkit-box-align:stretch;-ms-flex-align:stretch;align-items:stretch;-webkit-box-shadow:0 1px 2px rgba(10,10,10,.1);box-shadow:0 1px 2px rgba(10,10,10,.1);display:-webkit-box;display:-ms-flexbox;display:flex}.card-header-title{-webkit-box-align:center;-ms-flex-align:center;align-items:center;color:#363636;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;font-weight:700;padding:.75rem}.card-header-title.is-centered{-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center}.card-header-icon{-webkit-box-align:center;-ms-flex-align:center;align-items:center;cursor:pointer;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;padding:.75rem}.card-image{display:block;position:relative}.card-content{padding:1.5rem}.card-footer{border-top:1px solid #dbdbdb;-webkit-box-align:stretch;-ms-flex-align:stretch;align-items:stretch;display:-webkit-box;display:-ms-flexbox;display:flex}.card-footer-item{-webkit-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-preferred-size:0;flex-basis:0;-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;-ms-flex-negative:0;flex-shrink:0;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;padding:.75rem}.card-footer-item:not(:last-child){border-right:1px solid #dbdbdb}.card .media:not(:last-child){margin-bottom:.75rem}.dropdown{display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;position:relative;vertical-align:top}.dropdown.is-active .dropdown-menu,.dropdown.is-hoverable:hover .dropdown-menu{display:block}.dropdown.is-right .dropdown-menu{left:auto;right:0}.dropdown.is-up .dropdown-menu{bottom:100%;padding-bottom:4px;padding-top:unset;top:auto}.dropdown-menu{display:none;left:0;min-width:12rem;padding-top:4px;position:absolute;top:100%;z-index:20}.dropdown-content{background-color:#fff;border-radius:3px;-webkit-box-shadow:0 2px 3px rgba(10,10,10,.1),0 0 0 1px rgba(10,10,10,.1);box-shadow:0 2px 3px rgba(10,10,10,.1),0 0 0 1px rgba(10,10,10,.1);padding-bottom:.5rem;padding-top:.5rem}.dropdown-item{color:#4a4a4a;display:block;font-size:.875rem;line-height:1.5;padding:.375rem 1rem;position:relative}a.dropdown-item{padding-right:3rem;white-space:nowrap}a.dropdown-item:hover{background-color:#f5f5f5;color:#0a0a0a}a.dropdown-item.is-active{background-color:#3273dc;color:#fff}.dropdown-divider{background-color:#dbdbdb;border:none;display:block;height:1px;margin:.5rem 0}.level{-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between}.level:not(:last-child){margin-bottom:1.5rem}.level code{border-radius:3px}.level img{display:inline-block;vertical-align:top}.level.is-mobile{display:-webkit-box;display:-ms-flexbox;display:flex}.level.is-mobile .level-left,.level.is-mobile .level-right{display:-webkit-box;display:-ms-flexbox;display:flex}.level.is-mobile .level-left+.level-right{margin-top:0}.level.is-mobile .level-item{margin-right:.75rem}.level.is-mobile .level-item:not(:last-child){margin-bottom:0}.level.is-mobile .level-item:not(.is-narrow){-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1}@media screen and (min-width:769px),print{.level{display:-webkit-box;display:-ms-flexbox;display:flex}.level>.level-item:not(.is-narrow){-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1}}.level-item{-webkit-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-preferred-size:auto;flex-basis:auto;-webkit-box-flex:0;-ms-flex-positive:0;flex-grow:0;-ms-flex-negative:0;flex-shrink:0;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center}.level-item .subtitle,.level-item .title{margin-bottom:0}@media screen and (max-width:768px){.level-item:not(:last-child){margin-bottom:.75rem}}.level-left,.level-right{-ms-flex-preferred-size:auto;flex-basis:auto;-webkit-box-flex:0;-ms-flex-positive:0;flex-grow:0;-ms-flex-negative:0;flex-shrink:0}.level-left .level-item.is-flexible,.level-right .level-item.is-flexible{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1}@media screen and (min-width:769px),print{.level-left .level-item:not(:last-child),.level-right .level-item:not(:last-child){margin-right:.75rem}}.level-left{-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:start;-ms-flex-pack:start;justify-content:flex-start}@media screen and (max-width:768px){.level-left+.level-right{margin-top:1.5rem}}@media screen and (min-width:769px),print{.level-left{display:-webkit-box;display:-ms-flexbox;display:flex}}.level-right{-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:end;-ms-flex-pack:end;justify-content:flex-end}@media screen and (min-width:769px),print{.level-right{display:-webkit-box;display:-ms-flexbox;display:flex}}.media{-webkit-box-align:start;-ms-flex-align:start;align-items:flex-start;display:-webkit-box;display:-ms-flexbox;display:flex;text-align:left}.media .content:not(:last-child){margin-bottom:.75rem}.media .media{border-top:1px solid rgba(219,219,219,.5);display:-webkit-box;display:-ms-flexbox;display:flex;padding-top:.75rem}.media .media .content:not(:last-child),.media .media .control:not(:last-child){margin-bottom:.5rem}.media .media .media{padding-top:.5rem}.media .media .media+.media{margin-top:.5rem}.media+.media{border-top:1px solid rgba(219,219,219,.5);margin-top:1rem;padding-top:1rem}.media.is-large+.media{margin-top:1.5rem;padding-top:1.5rem}.media-left,.media-right{-ms-flex-preferred-size:auto;flex-basis:auto;-webkit-box-flex:0;-ms-flex-positive:0;flex-grow:0;-ms-flex-negative:0;flex-shrink:0}.media-left{margin-right:1rem}.media-right{margin-left:1rem}.media-content{-ms-flex-preferred-size:auto;flex-basis:auto;-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;-ms-flex-negative:1;flex-shrink:1;overflow:auto;text-align:left}.menu{font-size:1rem}.menu.is-small{font-size:.75rem}.menu.is-medium{font-size:1.25rem}.menu.is-large{font-size:1.5rem}.menu-list{line-height:1.25}.menu-list a{border-radius:2px;color:#4a4a4a;display:block;padding:.5em .75em}.menu-list a:hover{background-color:#f5f5f5;color:#363636}.menu-list a.is-active{background-color:#3273dc;color:#fff}.menu-list li ul{border-left:1px solid #dbdbdb;margin:.75em;padding-left:.75em}.menu-label{color:#7a7a7a;font-size:.75em;letter-spacing:.1em;text-transform:uppercase}.menu-label:not(:first-child){margin-top:1em}.menu-label:not(:last-child){margin-bottom:1em}.message{background-color:#f5f5f5;border-radius:3px;font-size:1rem}.message:not(:last-child){margin-bottom:1.5rem}.message strong{color:currentColor}.message a:not(.button):not(.tag){color:currentColor;text-decoration:underline}.message.is-small{font-size:.75rem}.message.is-medium{font-size:1.25rem}.message.is-large{font-size:1.5rem}.message.is-white{background-color:#fff}.message.is-white .message-header{background-color:#fff;color:#0a0a0a}.message.is-white .message-body{border-color:#fff;color:#4d4d4d}.message.is-black{background-color:#fafafa}.message.is-black .message-header{background-color:#0a0a0a;color:#fff}.message.is-black .message-body{border-color:#0a0a0a;color:#090909}.message.is-light{background-color:#fafafa}.message.is-light .message-header{background-color:#f5f5f5;color:#363636}.message.is-light .message-body{border-color:#f5f5f5;color:#505050}.message.is-dark{background-color:#fafafa}.message.is-dark .message-header{background-color:#363636;color:#f5f5f5}.message.is-dark .message-body{border-color:#363636;color:#2a2a2a}.message.is-primary{background-color:#f5fffd}.message.is-primary .message-header{background-color:#00d1b2;color:#fff}.message.is-primary .message-body{border-color:#00d1b2;color:#021310}.message.is-link{background-color:#f6f9fe}.message.is-link .message-header{background-color:#3273dc;color:#fff}.message.is-link .message-body{border-color:#3273dc;color:#22509a}.message.is-info{background-color:#f6fbfe}.message.is-info .message-header{background-color:#209cee;color:#fff}.message.is-info .message-body{border-color:#209cee;color:#12537e}.message.is-success{background-color:#f6fef9}.message.is-success .message-header{background-color:#23d160;color:#fff}.message.is-success .message-body{border-color:#23d160;color:#0e301a}.message.is-warning{background-color:#fffdf5}.message.is-warning .message-header{background-color:#ffdd57;color:rgba(0,0,0,.7)}.message.is-warning .message-body{border-color:#ffdd57;color:#3b3108}.message.is-danger{background-color:#fff5f7}.message.is-danger .message-header{background-color:#ff3860;color:#fff}.message.is-danger .message-body{border-color:#ff3860;color:#cd0930}.message-header{-webkit-box-align:center;-ms-flex-align:center;align-items:center;background-color:#4a4a4a;border-radius:3px 3px 0 0;color:#fff;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;line-height:1.25;padding:.5em .75em;position:relative}.message-header .delete{-webkit-box-flex:0;-ms-flex-positive:0;flex-grow:0;-ms-flex-negative:0;flex-shrink:0;margin-left:.75em}.message-header+.message-body{border-top-left-radius:0;border-top-right-radius:0;border-top:none}.message-body{border:1px solid #dbdbdb;border-radius:3px;color:#4a4a4a;padding:1em 1.25em}.message-body code,.message-body pre{background-color:#fff}.message-body pre code{background-color:transparent}.modal{bottom:0;left:0;position:absolute;right:0;top:0;-webkit-box-align:center;-ms-flex-align:center;align-items:center;display:none;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;overflow:hidden;position:fixed;z-index:40}.modal.is-active{display:-webkit-box;display:-ms-flexbox;display:flex}.modal-background{bottom:0;left:0;position:absolute;right:0;top:0;background-color:rgba(10,10,10,.86)}.modal-card,.modal-content{margin:0 20px;max-height:calc(100vh - 160px);overflow:auto;position:relative;width:100%}@media screen and (min-width:769px),print{.modal-card,.modal-content{margin:0 auto;max-height:calc(100vh - 40px);width:640px}}.modal-close{-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-moz-appearance:none;-webkit-appearance:none;background-color:rgba(10,10,10,.2);border:none;border-radius:290486px;cursor:pointer;display:inline-block;-webkit-box-flex:0;-ms-flex-positive:0;flex-grow:0;-ms-flex-negative:0;flex-shrink:0;font-size:0;height:20px;max-height:20px;max-width:20px;min-height:20px;min-width:20px;outline:0;position:relative;vertical-align:top;width:20px;background:0 0;height:40px;position:fixed;right:20px;top:20px;width:40px}.modal-close:after,.modal-close:before{background-color:#fff;content:"";display:block;left:50%;position:absolute;top:50%;-webkit-transform:translateX(-50%) translateY(-50%) rotate(45deg);transform:translateX(-50%) translateY(-50%) rotate(45deg);-webkit-transform-origin:center center;transform-origin:center center}.modal-close:before{height:2px;width:50%}.modal-close:after{height:50%;width:2px}.modal-close:focus,.modal-close:hover{background-color:rgba(10,10,10,.3)}.modal-close:active{background-color:rgba(10,10,10,.4)}.modal-close.is-small{height:16px;max-height:16px;max-width:16px;min-height:16px;min-width:16px;width:16px}.modal-close.is-medium{height:24px;max-height:24px;max-width:24px;min-height:24px;min-width:24px;width:24px}.modal-close.is-large{height:32px;max-height:32px;max-width:32px;min-height:32px;min-width:32px;width:32px}.modal-card{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;max-height:calc(100vh - 40px);overflow:hidden}.modal-card-foot,.modal-card-head{-webkit-box-align:center;-ms-flex-align:center;align-items:center;background-color:#f5f5f5;display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-negative:0;flex-shrink:0;-webkit-box-pack:start;-ms-flex-pack:start;justify-content:flex-start;padding:20px;position:relative}.modal-card-head{border-bottom:1px solid #dbdbdb;border-top-left-radius:5px;border-top-right-radius:5px}.modal-card-title{color:#363636;-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;-ms-flex-negative:0;flex-shrink:0;font-size:1.5rem;line-height:1}.modal-card-foot{border-bottom-left-radius:5px;border-bottom-right-radius:5px;border-top:1px solid #dbdbdb}.modal-card-foot .button:not(:last-child){margin-right:10px}.modal-card-body{-webkit-overflow-scrolling:touch;background-color:#fff;-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;-ms-flex-negative:1;flex-shrink:1;overflow:auto;padding:20px}.navbar{background-color:#fff;min-height:3.25rem;position:relative}.navbar.is-white{background-color:#fff;color:#0a0a0a}.navbar.is-white .navbar-brand .navbar-link,.navbar.is-white .navbar-brand>.navbar-item{color:#0a0a0a}.navbar.is-white .navbar-brand .navbar-link.is-active,.navbar.is-white .navbar-brand .navbar-link:hover,.navbar.is-white .navbar-brand>a.navbar-item.is-active,.navbar.is-white .navbar-brand>a.navbar-item:hover{background-color:#f2f2f2;color:#0a0a0a}.navbar.is-white .navbar-brand .navbar-link::after{border-color:#0a0a0a}@media screen and (min-width:1024px){.navbar.is-white .navbar-end .navbar-link,.navbar.is-white .navbar-end>.navbar-item,.navbar.is-white .navbar-start .navbar-link,.navbar.is-white .navbar-start>.navbar-item{color:#0a0a0a}.navbar.is-white .navbar-end .navbar-link.is-active,.navbar.is-white .navbar-end .navbar-link:hover,.navbar.is-white .navbar-end>a.navbar-item.is-active,.navbar.is-white .navbar-end>a.navbar-item:hover,.navbar.is-white .navbar-start .navbar-link.is-active,.navbar.is-white .navbar-start .navbar-link:hover,.navbar.is-white .navbar-start>a.navbar-item.is-active,.navbar.is-white .navbar-start>a.navbar-item:hover{background-color:#f2f2f2;color:#0a0a0a}.navbar.is-white .navbar-end .navbar-link::after,.navbar.is-white .navbar-start .navbar-link::after{border-color:#0a0a0a}.navbar.is-white .navbar-item.has-dropdown.is-active .navbar-link,.navbar.is-white .navbar-item.has-dropdown:hover .navbar-link{background-color:#f2f2f2;color:#0a0a0a}.navbar.is-white .navbar-dropdown a.navbar-item.is-active{background-color:#fff;color:#0a0a0a}}.navbar.is-black{background-color:#0a0a0a;color:#fff}.navbar.is-black .navbar-brand .navbar-link,.navbar.is-black .navbar-brand>.navbar-item{color:#fff}.navbar.is-black .navbar-brand .navbar-link.is-active,.navbar.is-black .navbar-brand .navbar-link:hover,.navbar.is-black .navbar-brand>a.navbar-item.is-active,.navbar.is-black .navbar-brand>a.navbar-item:hover{background-color:#000;color:#fff}.navbar.is-black .navbar-brand .navbar-link::after{border-color:#fff}@media screen and (min-width:1024px){.navbar.is-black .navbar-end .navbar-link,.navbar.is-black .navbar-end>.navbar-item,.navbar.is-black .navbar-start .navbar-link,.navbar.is-black .navbar-start>.navbar-item{color:#fff}.navbar.is-black .navbar-end .navbar-link.is-active,.navbar.is-black .navbar-end .navbar-link:hover,.navbar.is-black .navbar-end>a.navbar-item.is-active,.navbar.is-black .navbar-end>a.navbar-item:hover,.navbar.is-black .navbar-start .navbar-link.is-active,.navbar.is-black .navbar-start .navbar-link:hover,.navbar.is-black .navbar-start>a.navbar-item.is-active,.navbar.is-black .navbar-start>a.navbar-item:hover{background-color:#000;color:#fff}.navbar.is-black .navbar-end .navbar-link::after,.navbar.is-black .navbar-start .navbar-link::after{border-color:#fff}.navbar.is-black .navbar-item.has-dropdown.is-active .navbar-link,.navbar.is-black .navbar-item.has-dropdown:hover .navbar-link{background-color:#000;color:#fff}.navbar.is-black .navbar-dropdown a.navbar-item.is-active{background-color:#0a0a0a;color:#fff}}.navbar.is-light{background-color:#f5f5f5;color:#363636}.navbar.is-light .navbar-brand .navbar-link,.navbar.is-light .navbar-brand>.navbar-item{color:#363636}.navbar.is-light .navbar-brand .navbar-link.is-active,.navbar.is-light .navbar-brand .navbar-link:hover,.navbar.is-light .navbar-brand>a.navbar-item.is-active,.navbar.is-light .navbar-brand>a.navbar-item:hover{background-color:#e8e8e8;color:#363636}.navbar.is-light .navbar-brand .navbar-link::after{border-color:#363636}@media screen and (min-width:1024px){.navbar.is-light .navbar-end .navbar-link,.navbar.is-light .navbar-end>.navbar-item,.navbar.is-light .navbar-start .navbar-link,.navbar.is-light .navbar-start>.navbar-item{color:#363636}.navbar.is-light .navbar-end .navbar-link.is-active,.navbar.is-light .navbar-end .navbar-link:hover,.navbar.is-light .navbar-end>a.navbar-item.is-active,.navbar.is-light .navbar-end>a.navbar-item:hover,.navbar.is-light .navbar-start .navbar-link.is-active,.navbar.is-light .navbar-start .navbar-link:hover,.navbar.is-light .navbar-start>a.navbar-item.is-active,.navbar.is-light .navbar-start>a.navbar-item:hover{background-color:#e8e8e8;color:#363636}.navbar.is-light .navbar-end .navbar-link::after,.navbar.is-light .navbar-start .navbar-link::after{border-color:#363636}.navbar.is-light .navbar-item.has-dropdown.is-active .navbar-link,.navbar.is-light .navbar-item.has-dropdown:hover .navbar-link{background-color:#e8e8e8;color:#363636}.navbar.is-light .navbar-dropdown a.navbar-item.is-active{background-color:#f5f5f5;color:#363636}}.navbar.is-dark{background-color:#363636;color:#f5f5f5}.navbar.is-dark .navbar-brand .navbar-link,.navbar.is-dark .navbar-brand>.navbar-item{color:#f5f5f5}.navbar.is-dark .navbar-brand .navbar-link.is-active,.navbar.is-dark .navbar-brand .navbar-link:hover,.navbar.is-dark .navbar-brand>a.navbar-item.is-active,.navbar.is-dark .navbar-brand>a.navbar-item:hover{background-color:#292929;color:#f5f5f5}.navbar.is-dark .navbar-brand .navbar-link::after{border-color:#f5f5f5}@media screen and (min-width:1024px){.navbar.is-dark .navbar-end .navbar-link,.navbar.is-dark .navbar-end>.navbar-item,.navbar.is-dark .navbar-start .navbar-link,.navbar.is-dark .navbar-start>.navbar-item{color:#f5f5f5}.navbar.is-dark .navbar-end .navbar-link.is-active,.navbar.is-dark .navbar-end .navbar-link:hover,.navbar.is-dark .navbar-end>a.navbar-item.is-active,.navbar.is-dark .navbar-end>a.navbar-item:hover,.navbar.is-dark .navbar-start .navbar-link.is-active,.navbar.is-dark .navbar-start .navbar-link:hover,.navbar.is-dark .navbar-start>a.navbar-item.is-active,.navbar.is-dark .navbar-start>a.navbar-item:hover{background-color:#292929;color:#f5f5f5}.navbar.is-dark .navbar-end .navbar-link::after,.navbar.is-dark .navbar-start .navbar-link::after{border-color:#f5f5f5}.navbar.is-dark .navbar-item.has-dropdown.is-active .navbar-link,.navbar.is-dark .navbar-item.has-dropdown:hover .navbar-link{background-color:#292929;color:#f5f5f5}.navbar.is-dark .navbar-dropdown a.navbar-item.is-active{background-color:#363636;color:#f5f5f5}}.navbar.is-primary{background-color:#00d1b2;color:#fff}.navbar.is-primary .navbar-brand .navbar-link,.navbar.is-primary .navbar-brand>.navbar-item{color:#fff}.navbar.is-primary .navbar-brand .navbar-link.is-active,.navbar.is-primary .navbar-brand .navbar-link:hover,.navbar.is-primary .navbar-brand>a.navbar-item.is-active,.navbar.is-primary .navbar-brand>a.navbar-item:hover{background-color:#00b89c;color:#fff}.navbar.is-primary .navbar-brand .navbar-link::after{border-color:#fff}@media screen and (min-width:1024px){.navbar.is-primary .navbar-end .navbar-link,.navbar.is-primary .navbar-end>.navbar-item,.navbar.is-primary .navbar-start .navbar-link,.navbar.is-primary .navbar-start>.navbar-item{color:#fff}.navbar.is-primary .navbar-end .navbar-link.is-active,.navbar.is-primary .navbar-end .navbar-link:hover,.navbar.is-primary .navbar-end>a.navbar-item.is-active,.navbar.is-primary .navbar-end>a.navbar-item:hover,.navbar.is-primary .navbar-start .navbar-link.is-active,.navbar.is-primary .navbar-start .navbar-link:hover,.navbar.is-primary .navbar-start>a.navbar-item.is-active,.navbar.is-primary .navbar-start>a.navbar-item:hover{background-color:#00b89c;color:#fff}.navbar.is-primary .navbar-end .navbar-link::after,.navbar.is-primary .navbar-start .navbar-link::after{border-color:#fff}.navbar.is-primary .navbar-item.has-dropdown.is-active .navbar-link,.navbar.is-primary .navbar-item.has-dropdown:hover .navbar-link{background-color:#00b89c;color:#fff}.navbar.is-primary .navbar-dropdown a.navbar-item.is-active{background-color:#00d1b2;color:#fff}}.navbar.is-link{background-color:#3273dc;color:#fff}.navbar.is-link .navbar-brand .navbar-link,.navbar.is-link .navbar-brand>.navbar-item{color:#fff}.navbar.is-link .navbar-brand .navbar-link.is-active,.navbar.is-link .navbar-brand .navbar-link:hover,.navbar.is-link .navbar-brand>a.navbar-item.is-active,.navbar.is-link .navbar-brand>a.navbar-item:hover{background-color:#2366d1;color:#fff}.navbar.is-link .navbar-brand .navbar-link::after{border-color:#fff}@media screen and (min-width:1024px){.navbar.is-link .navbar-end .navbar-link,.navbar.is-link .navbar-end>.navbar-item,.navbar.is-link .navbar-start .navbar-link,.navbar.is-link .navbar-start>.navbar-item{color:#fff}.navbar.is-link .navbar-end .navbar-link.is-active,.navbar.is-link .navbar-end .navbar-link:hover,.navbar.is-link .navbar-end>a.navbar-item.is-active,.navbar.is-link .navbar-end>a.navbar-item:hover,.navbar.is-link .navbar-start .navbar-link.is-active,.navbar.is-link .navbar-start .navbar-link:hover,.navbar.is-link .navbar-start>a.navbar-item.is-active,.navbar.is-link .navbar-start>a.navbar-item:hover{background-color:#2366d1;color:#fff}.navbar.is-link .navbar-end .navbar-link::after,.navbar.is-link .navbar-start .navbar-link::after{border-color:#fff}.navbar.is-link .navbar-item.has-dropdown.is-active .navbar-link,.navbar.is-link .navbar-item.has-dropdown:hover .navbar-link{background-color:#2366d1;color:#fff}.navbar.is-link .navbar-dropdown a.navbar-item.is-active{background-color:#3273dc;color:#fff}}.navbar.is-info{background-color:#209cee;color:#fff}.navbar.is-info .navbar-brand .navbar-link,.navbar.is-info .navbar-brand>.navbar-item{color:#fff}.navbar.is-info .navbar-brand .navbar-link.is-active,.navbar.is-info .navbar-brand .navbar-link:hover,.navbar.is-info .navbar-brand>a.navbar-item.is-active,.navbar.is-info .navbar-brand>a.navbar-item:hover{background-color:#118fe4;color:#fff}.navbar.is-info .navbar-brand .navbar-link::after{border-color:#fff}@media screen and (min-width:1024px){.navbar.is-info .navbar-end .navbar-link,.navbar.is-info .navbar-end>.navbar-item,.navbar.is-info .navbar-start .navbar-link,.navbar.is-info .navbar-start>.navbar-item{color:#fff}.navbar.is-info .navbar-end .navbar-link.is-active,.navbar.is-info .navbar-end .navbar-link:hover,.navbar.is-info .navbar-end>a.navbar-item.is-active,.navbar.is-info .navbar-end>a.navbar-item:hover,.navbar.is-info .navbar-start .navbar-link.is-active,.navbar.is-info .navbar-start .navbar-link:hover,.navbar.is-info .navbar-start>a.navbar-item.is-active,.navbar.is-info .navbar-start>a.navbar-item:hover{background-color:#118fe4;color:#fff}.navbar.is-info .navbar-end .navbar-link::after,.navbar.is-info .navbar-start .navbar-link::after{border-color:#fff}.navbar.is-info .navbar-item.has-dropdown.is-active .navbar-link,.navbar.is-info .navbar-item.has-dropdown:hover .navbar-link{background-color:#118fe4;color:#fff}.navbar.is-info .navbar-dropdown a.navbar-item.is-active{background-color:#209cee;color:#fff}}.navbar.is-success{background-color:#23d160;color:#fff}.navbar.is-success .navbar-brand .navbar-link,.navbar.is-success .navbar-brand>.navbar-item{color:#fff}.navbar.is-success .navbar-brand .navbar-link.is-active,.navbar.is-success .navbar-brand .navbar-link:hover,.navbar.is-success .navbar-brand>a.navbar-item.is-active,.navbar.is-success .navbar-brand>a.navbar-item:hover{background-color:#20bc56;color:#fff}.navbar.is-success .navbar-brand .navbar-link::after{border-color:#fff}@media screen and (min-width:1024px){.navbar.is-success .navbar-end .navbar-link,.navbar.is-success .navbar-end>.navbar-item,.navbar.is-success .navbar-start .navbar-link,.navbar.is-success .navbar-start>.navbar-item{color:#fff}.navbar.is-success .navbar-end .navbar-link.is-active,.navbar.is-success .navbar-end .navbar-link:hover,.navbar.is-success .navbar-end>a.navbar-item.is-active,.navbar.is-success .navbar-end>a.navbar-item:hover,.navbar.is-success .navbar-start .navbar-link.is-active,.navbar.is-success .navbar-start .navbar-link:hover,.navbar.is-success .navbar-start>a.navbar-item.is-active,.navbar.is-success .navbar-start>a.navbar-item:hover{background-color:#20bc56;color:#fff}.navbar.is-success .navbar-end .navbar-link::after,.navbar.is-success .navbar-start .navbar-link::after{border-color:#fff}.navbar.is-success .navbar-item.has-dropdown.is-active .navbar-link,.navbar.is-success .navbar-item.has-dropdown:hover .navbar-link{background-color:#20bc56;color:#fff}.navbar.is-success .navbar-dropdown a.navbar-item.is-active{background-color:#23d160;color:#fff}}.navbar.is-warning{background-color:#ffdd57;color:rgba(0,0,0,.7)}.navbar.is-warning .navbar-brand .navbar-link,.navbar.is-warning .navbar-brand>.navbar-item{color:rgba(0,0,0,.7)}.navbar.is-warning .navbar-brand .navbar-link.is-active,.navbar.is-warning .navbar-brand .navbar-link:hover,.navbar.is-warning .navbar-brand>a.navbar-item.is-active,.navbar.is-warning .navbar-brand>a.navbar-item:hover{background-color:#ffd83d;color:rgba(0,0,0,.7)}.navbar.is-warning .navbar-brand .navbar-link::after{border-color:rgba(0,0,0,.7)}@media screen and (min-width:1024px){.navbar.is-warning .navbar-end .navbar-link,.navbar.is-warning .navbar-end>.navbar-item,.navbar.is-warning .navbar-start .navbar-link,.navbar.is-warning .navbar-start>.navbar-item{color:rgba(0,0,0,.7)}.navbar.is-warning .navbar-end .navbar-link.is-active,.navbar.is-warning .navbar-end .navbar-link:hover,.navbar.is-warning .navbar-end>a.navbar-item.is-active,.navbar.is-warning .navbar-end>a.navbar-item:hover,.navbar.is-warning .navbar-start .navbar-link.is-active,.navbar.is-warning .navbar-start .navbar-link:hover,.navbar.is-warning .navbar-start>a.navbar-item.is-active,.navbar.is-warning .navbar-start>a.navbar-item:hover{background-color:#ffd83d;color:rgba(0,0,0,.7)}.navbar.is-warning .navbar-end .navbar-link::after,.navbar.is-warning .navbar-start .navbar-link::after{border-color:rgba(0,0,0,.7)}.navbar.is-warning .navbar-item.has-dropdown.is-active .navbar-link,.navbar.is-warning .navbar-item.has-dropdown:hover .navbar-link{background-color:#ffd83d;color:rgba(0,0,0,.7)}.navbar.is-warning .navbar-dropdown a.navbar-item.is-active{background-color:#ffdd57;color:rgba(0,0,0,.7)}}.navbar.is-danger{background-color:#ff3860;color:#fff}.navbar.is-danger .navbar-brand .navbar-link,.navbar.is-danger .navbar-brand>.navbar-item{color:#fff}.navbar.is-danger .navbar-brand .navbar-link.is-active,.navbar.is-danger .navbar-brand .navbar-link:hover,.navbar.is-danger .navbar-brand>a.navbar-item.is-active,.navbar.is-danger .navbar-brand>a.navbar-item:hover{background-color:#ff1f4b;color:#fff}.navbar.is-danger .navbar-brand .navbar-link::after{border-color:#fff}@media screen and (min-width:1024px){.navbar.is-danger .navbar-end .navbar-link,.navbar.is-danger .navbar-end>.navbar-item,.navbar.is-danger .navbar-start .navbar-link,.navbar.is-danger .navbar-start>.navbar-item{color:#fff}.navbar.is-danger .navbar-end .navbar-link.is-active,.navbar.is-danger .navbar-end .navbar-link:hover,.navbar.is-danger .navbar-end>a.navbar-item.is-active,.navbar.is-danger .navbar-end>a.navbar-item:hover,.navbar.is-danger .navbar-start .navbar-link.is-active,.navbar.is-danger .navbar-start .navbar-link:hover,.navbar.is-danger .navbar-start>a.navbar-item.is-active,.navbar.is-danger .navbar-start>a.navbar-item:hover{background-color:#ff1f4b;color:#fff}.navbar.is-danger .navbar-end .navbar-link::after,.navbar.is-danger .navbar-start .navbar-link::after{border-color:#fff}.navbar.is-danger .navbar-item.has-dropdown.is-active .navbar-link,.navbar.is-danger .navbar-item.has-dropdown:hover .navbar-link{background-color:#ff1f4b;color:#fff}.navbar.is-danger .navbar-dropdown a.navbar-item.is-active{background-color:#ff3860;color:#fff}}.navbar>.container{-webkit-box-align:stretch;-ms-flex-align:stretch;align-items:stretch;display:-webkit-box;display:-ms-flexbox;display:flex;min-height:3.25rem;width:100%}.navbar.has-shadow{-webkit-box-shadow:0 2px 3px rgba(10,10,10,.1);box-shadow:0 2px 3px rgba(10,10,10,.1)}.navbar.is-fixed-bottom,.navbar.is-fixed-top{left:0;position:fixed;right:0;z-index:30}.navbar.is-fixed-bottom{bottom:0}.navbar.is-fixed-bottom.has-shadow{-webkit-box-shadow:0 -2px 3px rgba(10,10,10,.1);box-shadow:0 -2px 3px rgba(10,10,10,.1)}.navbar.is-fixed-top{top:0}html.has-navbar-fixed-top{padding-top:3.25rem}html.has-navbar-fixed-bottom{padding-bottom:3.25rem}.navbar-brand,.navbar-tabs{-webkit-box-align:stretch;-ms-flex-align:stretch;align-items:stretch;display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-negative:0;flex-shrink:0;min-height:3.25rem}.navbar-tabs{-webkit-overflow-scrolling:touch;max-width:100vw;overflow-x:auto;overflow-y:hidden}.navbar-burger{cursor:pointer;display:block;height:3.25rem;position:relative;width:3.25rem;margin-left:auto}.navbar-burger span{background-color:currentColor;display:block;height:1px;left:calc(50% - 8px);position:absolute;-webkit-transform-origin:center;transform-origin:center;-webkit-transition-duration:86ms;transition-duration:86ms;-webkit-transition-property:background-color,opacity,-webkit-transform;transition-property:background-color,opacity,-webkit-transform;transition-property:background-color,opacity,transform;transition-property:background-color,opacity,transform,-webkit-transform;-webkit-transition-timing-function:ease-out;transition-timing-function:ease-out;width:16px}.navbar-burger span:nth-child(1){top:calc(50% - 6px)}.navbar-burger span:nth-child(2){top:calc(50% - 1px)}.navbar-burger span:nth-child(3){top:calc(50% + 4px)}.navbar-burger:hover{background-color:rgba(0,0,0,.05)}.navbar-burger.is-active span:nth-child(1){-webkit-transform:translateY(5px) rotate(45deg);transform:translateY(5px) rotate(45deg)}.navbar-burger.is-active span:nth-child(2){opacity:0}.navbar-burger.is-active span:nth-child(3){-webkit-transform:translateY(-5px) rotate(-45deg);transform:translateY(-5px) rotate(-45deg)}.navbar-menu{display:none}.navbar-item,.navbar-link{color:#4a4a4a;display:block;line-height:1.5;padding:.5rem 1rem;position:relative}a.navbar-item.is-active,a.navbar-item:hover,a.navbar-link.is-active,a.navbar-link:hover{background-color:#f5f5f5;color:#3273dc}.navbar-item{-webkit-box-flex:0;-ms-flex-positive:0;flex-grow:0;-ms-flex-negative:0;flex-shrink:0}.navbar-item img{max-height:1.75rem}.navbar-item.has-dropdown{padding:0}.navbar-item.is-expanded{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;-ms-flex-negative:1;flex-shrink:1}.navbar-item.is-tab{border-bottom:1px solid transparent;min-height:3.25rem;padding-bottom:calc(.5rem - 1px)}.navbar-item.is-tab:hover{background-color:transparent;border-bottom-color:#3273dc}.navbar-item.is-tab.is-active{background-color:transparent;border-bottom-color:#3273dc;border-bottom-style:solid;border-bottom-width:3px;color:#3273dc;padding-bottom:calc(.5rem - 3px)}.navbar-content{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;-ms-flex-negative:1;flex-shrink:1}.navbar-link{padding-right:2.5em}.navbar-dropdown{font-size:.875rem;padding-bottom:.5rem;padding-top:.5rem}.navbar-dropdown .navbar-item{padding-left:1.5rem;padding-right:1.5rem}.navbar-divider{background-color:#dbdbdb;border:none;display:none;height:1px;margin:.5rem 0}@media screen and (max-width:1023px){.navbar>.container{display:block}.navbar-brand .navbar-item,.navbar-tabs .navbar-item{-webkit-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-ms-flexbox;display:flex}.navbar-menu{background-color:#fff;-webkit-box-shadow:0 8px 16px rgba(10,10,10,.1);box-shadow:0 8px 16px rgba(10,10,10,.1);padding:.5rem 0}.navbar-menu.is-active{display:block}.navbar.is-fixed-bottom-touch,.navbar.is-fixed-top-touch{left:0;position:fixed;right:0;z-index:30}.navbar.is-fixed-bottom-touch{bottom:0}.navbar.is-fixed-bottom-touch.has-shadow{-webkit-box-shadow:0 -2px 3px rgba(10,10,10,.1);box-shadow:0 -2px 3px rgba(10,10,10,.1)}.navbar.is-fixed-top-touch{top:0}.navbar.is-fixed-top .navbar-menu,.navbar.is-fixed-top-touch .navbar-menu{-webkit-overflow-scrolling:touch;max-height:calc(100vh - 3.25rem);overflow:auto}html.has-navbar-fixed-top-touch{padding-top:3.25rem}html.has-navbar-fixed-bottom-touch{padding-bottom:3.25rem}}@media screen and (min-width:1024px){.navbar,.navbar-end,.navbar-menu,.navbar-start{-webkit-box-align:stretch;-ms-flex-align:stretch;align-items:stretch;display:-webkit-box;display:-ms-flexbox;display:flex}.navbar{min-height:3.25rem}.navbar.is-transparent a.navbar-item.is-active,.navbar.is-transparent a.navbar-item:hover,.navbar.is-transparent a.navbar-link.is-active,.navbar.is-transparent a.navbar-link:hover{background-color:transparent!important}.navbar.is-transparent .navbar-item.has-dropdown.is-active .navbar-link,.navbar.is-transparent .navbar-item.has-dropdown.is-hoverable:hover .navbar-link{background-color:transparent!important}.navbar.is-transparent .navbar-dropdown a.navbar-item:hover{background-color:#f5f5f5;color:#0a0a0a}.navbar.is-transparent .navbar-dropdown a.navbar-item.is-active{background-color:#f5f5f5;color:#3273dc}.navbar-burger{display:none}.navbar-item,.navbar-link{-webkit-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-ms-flexbox;display:flex}.navbar-item.has-dropdown{-webkit-box-align:stretch;-ms-flex-align:stretch;align-items:stretch}.navbar-item.has-dropdown-up .navbar-link::after{-webkit-transform:rotate(135deg) translate(.25em,-.25em);transform:rotate(135deg) translate(.25em,-.25em)}.navbar-item.has-dropdown-up .navbar-dropdown{border-bottom:1px solid #dbdbdb;border-radius:5px 5px 0 0;border-top:none;bottom:100%;-webkit-box-shadow:0 -8px 8px rgba(10,10,10,.1);box-shadow:0 -8px 8px rgba(10,10,10,.1);top:auto}.navbar-item.is-active .navbar-dropdown,.navbar-item.is-hoverable:hover .navbar-dropdown{display:block}.navbar-item.is-active .navbar-dropdown.is-boxed,.navbar-item.is-hoverable:hover .navbar-dropdown.is-boxed{opacity:1;pointer-events:auto;-webkit-transform:translateY(0);transform:translateY(0)}.navbar-link::after{border:1px solid #3273dc;border-right:0;border-top:0;content:" ";display:block;height:.5em;pointer-events:none;position:absolute;-webkit-transform:rotate(-45deg);transform:rotate(-45deg);-webkit-transform-origin:center;transform-origin:center;width:.5em;margin-top:-.375em;right:1.125em;top:50%}.navbar-menu{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;-ms-flex-negative:0;flex-shrink:0}.navbar-start{-webkit-box-pack:start;-ms-flex-pack:start;justify-content:flex-start;margin-right:auto}.navbar-end{-webkit-box-pack:end;-ms-flex-pack:end;justify-content:flex-end;margin-left:auto}.navbar-dropdown{background-color:#fff;border-bottom-left-radius:5px;border-bottom-right-radius:5px;border-top:1px solid #dbdbdb;-webkit-box-shadow:0 8px 8px rgba(10,10,10,.1);box-shadow:0 8px 8px rgba(10,10,10,.1);display:none;font-size:.875rem;left:0;min-width:100%;position:absolute;top:100%;z-index:20}.navbar-dropdown .navbar-item{padding:.375rem 1rem;white-space:nowrap}.navbar-dropdown a.navbar-item{padding-right:3rem}.navbar-dropdown a.navbar-item:hover{background-color:#f5f5f5;color:#0a0a0a}.navbar-dropdown a.navbar-item.is-active{background-color:#f5f5f5;color:#3273dc}.navbar-dropdown.is-boxed{border-radius:5px;border-top:none;-webkit-box-shadow:0 8px 8px rgba(10,10,10,.1),0 0 0 1px rgba(10,10,10,.1);box-shadow:0 8px 8px rgba(10,10,10,.1),0 0 0 1px rgba(10,10,10,.1);display:block;opacity:0;pointer-events:none;top:calc(100% + (-4px));-webkit-transform:translateY(-5px);transform:translateY(-5px);-webkit-transition-duration:86ms;transition-duration:86ms;-webkit-transition-property:opacity,-webkit-transform;transition-property:opacity,-webkit-transform;transition-property:opacity,transform;transition-property:opacity,transform,-webkit-transform}.navbar-dropdown.is-right{left:auto;right:0}.navbar-divider{display:block}.container>.navbar .navbar-brand,.navbar>.container .navbar-brand{margin-left:-1rem}.container>.navbar .navbar-menu,.navbar>.container .navbar-menu{margin-right:-1rem}.navbar.is-fixed-bottom-desktop,.navbar.is-fixed-top-desktop{left:0;position:fixed;right:0;z-index:30}.navbar.is-fixed-bottom-desktop{bottom:0}.navbar.is-fixed-bottom-desktop.has-shadow{-webkit-box-shadow:0 -2px 3px rgba(10,10,10,.1);box-shadow:0 -2px 3px rgba(10,10,10,.1)}.navbar.is-fixed-top-desktop{top:0}html.has-navbar-fixed-top-desktop{padding-top:3.25rem}html.has-navbar-fixed-bottom-desktop{padding-bottom:3.25rem}a.navbar-item.is-active,a.navbar-link.is-active{color:#0a0a0a}a.navbar-item.is-active:not(:hover),a.navbar-link.is-active:not(:hover){background-color:transparent}.navbar-item.has-dropdown.is-active .navbar-link,.navbar-item.has-dropdown:hover .navbar-link{background-color:#f5f5f5}}.pagination{font-size:1rem;margin:-.25rem}.pagination.is-small{font-size:.75rem}.pagination.is-medium{font-size:1.25rem}.pagination.is-large{font-size:1.5rem}.pagination.is-rounded .pagination-next,.pagination.is-rounded .pagination-previous{padding-left:1em;padding-right:1em;border-radius:290486px}.pagination.is-rounded .pagination-link{border-radius:290486px}.pagination,.pagination-list{-webkit-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;text-align:center}.pagination-ellipsis,.pagination-link,.pagination-next,.pagination-previous{-moz-appearance:none;-webkit-appearance:none;-webkit-box-align:center;-ms-flex-align:center;align-items:center;border:1px solid transparent;border-radius:3px;-webkit-box-shadow:none;box-shadow:none;display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;font-size:1rem;height:2.25em;-webkit-box-pack:start;-ms-flex-pack:start;justify-content:flex-start;line-height:1.5;padding-bottom:calc(.375em - 1px);padding-left:calc(.625em - 1px);padding-right:calc(.625em - 1px);padding-top:calc(.375em - 1px);position:relative;vertical-align:top;-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;font-size:1em;padding-left:.5em;padding-right:.5em;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;margin:.25rem;text-align:center}.pagination-ellipsis.is-active,.pagination-ellipsis.is-focused,.pagination-ellipsis:active,.pagination-ellipsis:focus,.pagination-link.is-active,.pagination-link.is-focused,.pagination-link:active,.pagination-link:focus,.pagination-next.is-active,.pagination-next.is-focused,.pagination-next:active,.pagination-next:focus,.pagination-previous.is-active,.pagination-previous.is-focused,.pagination-previous:active,.pagination-previous:focus{outline:0}.pagination-ellipsis[disabled],.pagination-link[disabled],.pagination-next[disabled],.pagination-previous[disabled]{cursor:not-allowed}.pagination-link,.pagination-next,.pagination-previous{border-color:#dbdbdb;color:#363636;min-width:2.25em}.pagination-link:hover,.pagination-next:hover,.pagination-previous:hover{border-color:#b5b5b5;color:#363636}.pagination-link:focus,.pagination-next:focus,.pagination-previous:focus{border-color:#3273dc}.pagination-link:active,.pagination-next:active,.pagination-previous:active{-webkit-box-shadow:inset 0 1px 2px rgba(10,10,10,.2);box-shadow:inset 0 1px 2px rgba(10,10,10,.2)}.pagination-link[disabled],.pagination-next[disabled],.pagination-previous[disabled]{background-color:#dbdbdb;border-color:#dbdbdb;-webkit-box-shadow:none;box-shadow:none;color:#7a7a7a;opacity:.5}.pagination-next,.pagination-previous{padding-left:.75em;padding-right:.75em;white-space:nowrap}.pagination-link.is-current{background-color:#3273dc;border-color:#3273dc;color:#fff}.pagination-ellipsis{color:#b5b5b5;pointer-events:none}.pagination-list{-ms-flex-wrap:wrap;flex-wrap:wrap}@media screen and (max-width:768px){.pagination{-ms-flex-wrap:wrap;flex-wrap:wrap}.pagination-next,.pagination-previous{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;-ms-flex-negative:1;flex-shrink:1}.pagination-list li{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;-ms-flex-negative:1;flex-shrink:1}}@media screen and (min-width:769px),print{.pagination-list{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;-ms-flex-negative:1;flex-shrink:1;-webkit-box-pack:start;-ms-flex-pack:start;justify-content:flex-start;-webkit-box-ordinal-group:2;-ms-flex-order:1;order:1}.pagination-previous{-webkit-box-ordinal-group:3;-ms-flex-order:2;order:2}.pagination-next{-webkit-box-ordinal-group:4;-ms-flex-order:3;order:3}.pagination{-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between}.pagination.is-centered .pagination-previous{-webkit-box-ordinal-group:2;-ms-flex-order:1;order:1}.pagination.is-centered .pagination-list{-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;-webkit-box-ordinal-group:3;-ms-flex-order:2;order:2}.pagination.is-centered .pagination-next{-webkit-box-ordinal-group:4;-ms-flex-order:3;order:3}.pagination.is-right .pagination-previous{-webkit-box-ordinal-group:2;-ms-flex-order:1;order:1}.pagination.is-right .pagination-next{-webkit-box-ordinal-group:3;-ms-flex-order:2;order:2}.pagination.is-right .pagination-list{-webkit-box-pack:end;-ms-flex-pack:end;justify-content:flex-end;-webkit-box-ordinal-group:4;-ms-flex-order:3;order:3}}.panel{font-size:1rem}.panel:not(:last-child){margin-bottom:1.5rem}.panel-block,.panel-heading,.panel-tabs{border-bottom:1px solid #dbdbdb;border-left:1px solid #dbdbdb;border-right:1px solid #dbdbdb}.panel-block:first-child,.panel-heading:first-child,.panel-tabs:first-child{border-top:1px solid #dbdbdb}.panel-heading{background-color:#f5f5f5;border-radius:3px 3px 0 0;color:#363636;font-size:1.25em;font-weight:300;line-height:1.25;padding:.5em .75em}.panel-tabs{-webkit-box-align:end;-ms-flex-align:end;align-items:flex-end;display:-webkit-box;display:-ms-flexbox;display:flex;font-size:.875em;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center}.panel-tabs a{border-bottom:1px solid #dbdbdb;margin-bottom:-1px;padding:.5em}.panel-tabs a.is-active{border-bottom-color:#4a4a4a;color:#363636}.panel-list a{color:#4a4a4a}.panel-list a:hover{color:#3273dc}.panel-block{-webkit-box-align:center;-ms-flex-align:center;align-items:center;color:#363636;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:start;-ms-flex-pack:start;justify-content:flex-start;padding:.5em .75em}.panel-block input[type=checkbox]{margin-right:.75em}.panel-block>.control{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;-ms-flex-negative:1;flex-shrink:1;width:100%}.panel-block.is-wrapped{-ms-flex-wrap:wrap;flex-wrap:wrap}.panel-block.is-active{border-left-color:#3273dc;color:#363636}.panel-block.is-active .panel-icon{color:#3273dc}a.panel-block,label.panel-block{cursor:pointer}a.panel-block:hover,label.panel-block:hover{background-color:#f5f5f5}.panel-icon{display:inline-block;font-size:14px;height:1em;line-height:1em;text-align:center;vertical-align:top;width:1em;color:#7a7a7a;margin-right:.75em}.panel-icon .fa{font-size:inherit;line-height:inherit}.tabs{-webkit-overflow-scrolling:touch;-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-box-align:stretch;-ms-flex-align:stretch;align-items:stretch;display:-webkit-box;display:-ms-flexbox;display:flex;font-size:1rem;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;overflow:hidden;overflow-x:auto;white-space:nowrap}.tabs:not(:last-child){margin-bottom:1.5rem}.tabs a{-webkit-box-align:center;-ms-flex-align:center;align-items:center;border-bottom-color:#dbdbdb;border-bottom-style:solid;border-bottom-width:1px;color:#4a4a4a;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;margin-bottom:-1px;padding:.5em 1em;vertical-align:top}.tabs a:hover{border-bottom-color:#363636;color:#363636}.tabs li{display:block}.tabs li.is-active a{border-bottom-color:#3273dc;color:#3273dc}.tabs ul{-webkit-box-align:center;-ms-flex-align:center;align-items:center;border-bottom-color:#dbdbdb;border-bottom-style:solid;border-bottom-width:1px;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;-ms-flex-negative:0;flex-shrink:0;-webkit-box-pack:start;-ms-flex-pack:start;justify-content:flex-start}.tabs ul.is-left{padding-right:.75em}.tabs ul.is-center{-webkit-box-flex:0;-ms-flex:none;flex:none;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;padding-left:.75em;padding-right:.75em}.tabs ul.is-right{-webkit-box-pack:end;-ms-flex-pack:end;justify-content:flex-end;padding-left:.75em}.tabs .icon:first-child{margin-right:.5em}.tabs .icon:last-child{margin-left:.5em}.tabs.is-centered ul{-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center}.tabs.is-right ul{-webkit-box-pack:end;-ms-flex-pack:end;justify-content:flex-end}.tabs.is-boxed a{border:1px solid transparent;border-radius:3px 3px 0 0}.tabs.is-boxed a:hover{background-color:#f5f5f5;border-bottom-color:#dbdbdb}.tabs.is-boxed li.is-active a{background-color:#fff;border-color:#dbdbdb;border-bottom-color:transparent!important}.tabs.is-fullwidth li{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;-ms-flex-negative:0;flex-shrink:0}.tabs.is-toggle a{border-color:#dbdbdb;border-style:solid;border-width:1px;margin-bottom:0;position:relative}.tabs.is-toggle a:hover{background-color:#f5f5f5;border-color:#b5b5b5;z-index:2}.tabs.is-toggle li+li{margin-left:-1px}.tabs.is-toggle li:first-child a{border-radius:3px 0 0 3px}.tabs.is-toggle li:last-child a{border-radius:0 3px 3px 0}.tabs.is-toggle li.is-active a{background-color:#3273dc;border-color:#3273dc;color:#fff;z-index:1}.tabs.is-toggle ul{border-bottom:none}.tabs.is-toggle.is-toggle-rounded li:first-child a{border-bottom-left-radius:290486px;border-top-left-radius:290486px;padding-left:1.25em}.tabs.is-toggle.is-toggle-rounded li:last-child a{border-bottom-right-radius:290486px;border-top-right-radius:290486px;padding-right:1.25em}.tabs.is-small{font-size:.75rem}.tabs.is-medium{font-size:1.25rem}.tabs.is-large{font-size:1.5rem}.column{display:block;-ms-flex-preferred-size:0;flex-basis:0;-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;-ms-flex-negative:1;flex-shrink:1;padding:.75rem}.columns.is-mobile>.column.is-narrow{-webkit-box-flex:0;-ms-flex:none;flex:none}.columns.is-mobile>.column.is-full{-webkit-box-flex:0;-ms-flex:none;flex:none;width:100%}.columns.is-mobile>.column.is-three-quarters{-webkit-box-flex:0;-ms-flex:none;flex:none;width:75%}.columns.is-mobile>.column.is-two-thirds{-webkit-box-flex:0;-ms-flex:none;flex:none;width:66.6666%}.columns.is-mobile>.column.is-half{-webkit-box-flex:0;-ms-flex:none;flex:none;width:50%}.columns.is-mobile>.column.is-one-third{-webkit-box-flex:0;-ms-flex:none;flex:none;width:33.3333%}.columns.is-mobile>.column.is-one-quarter{-webkit-box-flex:0;-ms-flex:none;flex:none;width:25%}.columns.is-mobile>.column.is-one-fifth{-webkit-box-flex:0;-ms-flex:none;flex:none;width:20%}.columns.is-mobile>.column.is-two-fifths{-webkit-box-flex:0;-ms-flex:none;flex:none;width:40%}.columns.is-mobile>.column.is-three-fifths{-webkit-box-flex:0;-ms-flex:none;flex:none;width:60%}.columns.is-mobile>.column.is-four-fifths{-webkit-box-flex:0;-ms-flex:none;flex:none;width:80%}.columns.is-mobile>.column.is-offset-three-quarters{margin-left:75%}.columns.is-mobile>.column.is-offset-two-thirds{margin-left:66.6666%}.columns.is-mobile>.column.is-offset-half{margin-left:50%}.columns.is-mobile>.column.is-offset-one-third{margin-left:33.3333%}.columns.is-mobile>.column.is-offset-one-quarter{margin-left:25%}.columns.is-mobile>.column.is-offset-one-fifth{margin-left:20%}.columns.is-mobile>.column.is-offset-two-fifths{margin-left:40%}.columns.is-mobile>.column.is-offset-three-fifths{margin-left:60%}.columns.is-mobile>.column.is-offset-four-fifths{margin-left:80%}.columns.is-mobile>.column.is-1{-webkit-box-flex:0;-ms-flex:none;flex:none;width:8.33333%}.columns.is-mobile>.column.is-offset-1{margin-left:8.33333%}.columns.is-mobile>.column.is-2{-webkit-box-flex:0;-ms-flex:none;flex:none;width:16.66667%}.columns.is-mobile>.column.is-offset-2{margin-left:16.66667%}.columns.is-mobile>.column.is-3{-webkit-box-flex:0;-ms-flex:none;flex:none;width:25%}.columns.is-mobile>.column.is-offset-3{margin-left:25%}.columns.is-mobile>.column.is-4{-webkit-box-flex:0;-ms-flex:none;flex:none;width:33.33333%}.columns.is-mobile>.column.is-offset-4{margin-left:33.33333%}.columns.is-mobile>.column.is-5{-webkit-box-flex:0;-ms-flex:none;flex:none;width:41.66667%}.columns.is-mobile>.column.is-offset-5{margin-left:41.66667%}.columns.is-mobile>.column.is-6{-webkit-box-flex:0;-ms-flex:none;flex:none;width:50%}.columns.is-mobile>.column.is-offset-6{margin-left:50%}.columns.is-mobile>.column.is-7{-webkit-box-flex:0;-ms-flex:none;flex:none;width:58.33333%}.columns.is-mobile>.column.is-offset-7{margin-left:58.33333%}.columns.is-mobile>.column.is-8{-webkit-box-flex:0;-ms-flex:none;flex:none;width:66.66667%}.columns.is-mobile>.column.is-offset-8{margin-left:66.66667%}.columns.is-mobile>.column.is-9{-webkit-box-flex:0;-ms-flex:none;flex:none;width:75%}.columns.is-mobile>.column.is-offset-9{margin-left:75%}.columns.is-mobile>.column.is-10{-webkit-box-flex:0;-ms-flex:none;flex:none;width:83.33333%}.columns.is-mobile>.column.is-offset-10{margin-left:83.33333%}.columns.is-mobile>.column.is-11{-webkit-box-flex:0;-ms-flex:none;flex:none;width:91.66667%}.columns.is-mobile>.column.is-offset-11{margin-left:91.66667%}.columns.is-mobile>.column.is-12{-webkit-box-flex:0;-ms-flex:none;flex:none;width:100%}.columns.is-mobile>.column.is-offset-12{margin-left:100%}@media screen and (max-width:768px){.column.is-narrow-mobile{-webkit-box-flex:0;-ms-flex:none;flex:none}.column.is-full-mobile{-webkit-box-flex:0;-ms-flex:none;flex:none;width:100%}.column.is-three-quarters-mobile{-webkit-box-flex:0;-ms-flex:none;flex:none;width:75%}.column.is-two-thirds-mobile{-webkit-box-flex:0;-ms-flex:none;flex:none;width:66.6666%}.column.is-half-mobile{-webkit-box-flex:0;-ms-flex:none;flex:none;width:50%}.column.is-one-third-mobile{-webkit-box-flex:0;-ms-flex:none;flex:none;width:33.3333%}.column.is-one-quarter-mobile{-webkit-box-flex:0;-ms-flex:none;flex:none;width:25%}.column.is-one-fifth-mobile{-webkit-box-flex:0;-ms-flex:none;flex:none;width:20%}.column.is-two-fifths-mobile{-webkit-box-flex:0;-ms-flex:none;flex:none;width:40%}.column.is-three-fifths-mobile{-webkit-box-flex:0;-ms-flex:none;flex:none;width:60%}.column.is-four-fifths-mobile{-webkit-box-flex:0;-ms-flex:none;flex:none;width:80%}.column.is-offset-three-quarters-mobile{margin-left:75%}.column.is-offset-two-thirds-mobile{margin-left:66.6666%}.column.is-offset-half-mobile{margin-left:50%}.column.is-offset-one-third-mobile{margin-left:33.3333%}.column.is-offset-one-quarter-mobile{margin-left:25%}.column.is-offset-one-fifth-mobile{margin-left:20%}.column.is-offset-two-fifths-mobile{margin-left:40%}.column.is-offset-three-fifths-mobile{margin-left:60%}.column.is-offset-four-fifths-mobile{margin-left:80%}.column.is-1-mobile{-webkit-box-flex:0;-ms-flex:none;flex:none;width:8.33333%}.column.is-offset-1-mobile{margin-left:8.33333%}.column.is-2-mobile{-webkit-box-flex:0;-ms-flex:none;flex:none;width:16.66667%}.column.is-offset-2-mobile{margin-left:16.66667%}.column.is-3-mobile{-webkit-box-flex:0;-ms-flex:none;flex:none;width:25%}.column.is-offset-3-mobile{margin-left:25%}.column.is-4-mobile{-webkit-box-flex:0;-ms-flex:none;flex:none;width:33.33333%}.column.is-offset-4-mobile{margin-left:33.33333%}.column.is-5-mobile{-webkit-box-flex:0;-ms-flex:none;flex:none;width:41.66667%}.column.is-offset-5-mobile{margin-left:41.66667%}.column.is-6-mobile{-webkit-box-flex:0;-ms-flex:none;flex:none;width:50%}.column.is-offset-6-mobile{margin-left:50%}.column.is-7-mobile{-webkit-box-flex:0;-ms-flex:none;flex:none;width:58.33333%}.column.is-offset-7-mobile{margin-left:58.33333%}.column.is-8-mobile{-webkit-box-flex:0;-ms-flex:none;flex:none;width:66.66667%}.column.is-offset-8-mobile{margin-left:66.66667%}.column.is-9-mobile{-webkit-box-flex:0;-ms-flex:none;flex:none;width:75%}.column.is-offset-9-mobile{margin-left:75%}.column.is-10-mobile{-webkit-box-flex:0;-ms-flex:none;flex:none;width:83.33333%}.column.is-offset-10-mobile{margin-left:83.33333%}.column.is-11-mobile{-webkit-box-flex:0;-ms-flex:none;flex:none;width:91.66667%}.column.is-offset-11-mobile{margin-left:91.66667%}.column.is-12-mobile{-webkit-box-flex:0;-ms-flex:none;flex:none;width:100%}.column.is-offset-12-mobile{margin-left:100%}}@media screen and (min-width:769px),print{.column.is-narrow,.column.is-narrow-tablet{-webkit-box-flex:0;-ms-flex:none;flex:none}.column.is-full,.column.is-full-tablet{-webkit-box-flex:0;-ms-flex:none;flex:none;width:100%}.column.is-three-quarters,.column.is-three-quarters-tablet{-webkit-box-flex:0;-ms-flex:none;flex:none;width:75%}.column.is-two-thirds,.column.is-two-thirds-tablet{-webkit-box-flex:0;-ms-flex:none;flex:none;width:66.6666%}.column.is-half,.column.is-half-tablet{-webkit-box-flex:0;-ms-flex:none;flex:none;width:50%}.column.is-one-third,.column.is-one-third-tablet{-webkit-box-flex:0;-ms-flex:none;flex:none;width:33.3333%}.column.is-one-quarter,.column.is-one-quarter-tablet{-webkit-box-flex:0;-ms-flex:none;flex:none;width:25%}.column.is-one-fifth,.column.is-one-fifth-tablet{-webkit-box-flex:0;-ms-flex:none;flex:none;width:20%}.column.is-two-fifths,.column.is-two-fifths-tablet{-webkit-box-flex:0;-ms-flex:none;flex:none;width:40%}.column.is-three-fifths,.column.is-three-fifths-tablet{-webkit-box-flex:0;-ms-flex:none;flex:none;width:60%}.column.is-four-fifths,.column.is-four-fifths-tablet{-webkit-box-flex:0;-ms-flex:none;flex:none;width:80%}.column.is-offset-three-quarters,.column.is-offset-three-quarters-tablet{margin-left:75%}.column.is-offset-two-thirds,.column.is-offset-two-thirds-tablet{margin-left:66.6666%}.column.is-offset-half,.column.is-offset-half-tablet{margin-left:50%}.column.is-offset-one-third,.column.is-offset-one-third-tablet{margin-left:33.3333%}.column.is-offset-one-quarter,.column.is-offset-one-quarter-tablet{margin-left:25%}.column.is-offset-one-fifth,.column.is-offset-one-fifth-tablet{margin-left:20%}.column.is-offset-two-fifths,.column.is-offset-two-fifths-tablet{margin-left:40%}.column.is-offset-three-fifths,.column.is-offset-three-fifths-tablet{margin-left:60%}.column.is-offset-four-fifths,.column.is-offset-four-fifths-tablet{margin-left:80%}.column.is-1,.column.is-1-tablet{-webkit-box-flex:0;-ms-flex:none;flex:none;width:8.33333%}.column.is-offset-1,.column.is-offset-1-tablet{margin-left:8.33333%}.column.is-2,.column.is-2-tablet{-webkit-box-flex:0;-ms-flex:none;flex:none;width:16.66667%}.column.is-offset-2,.column.is-offset-2-tablet{margin-left:16.66667%}.column.is-3,.column.is-3-tablet{-webkit-box-flex:0;-ms-flex:none;flex:none;width:25%}.column.is-offset-3,.column.is-offset-3-tablet{margin-left:25%}.column.is-4,.column.is-4-tablet{-webkit-box-flex:0;-ms-flex:none;flex:none;width:33.33333%}.column.is-offset-4,.column.is-offset-4-tablet{margin-left:33.33333%}.column.is-5,.column.is-5-tablet{-webkit-box-flex:0;-ms-flex:none;flex:none;width:41.66667%}.column.is-offset-5,.column.is-offset-5-tablet{margin-left:41.66667%}.column.is-6,.column.is-6-tablet{-webkit-box-flex:0;-ms-flex:none;flex:none;width:50%}.column.is-offset-6,.column.is-offset-6-tablet{margin-left:50%}.column.is-7,.column.is-7-tablet{-webkit-box-flex:0;-ms-flex:none;flex:none;width:58.33333%}.column.is-offset-7,.column.is-offset-7-tablet{margin-left:58.33333%}.column.is-8,.column.is-8-tablet{-webkit-box-flex:0;-ms-flex:none;flex:none;width:66.66667%}.column.is-offset-8,.column.is-offset-8-tablet{margin-left:66.66667%}.column.is-9,.column.is-9-tablet{-webkit-box-flex:0;-ms-flex:none;flex:none;width:75%}.column.is-offset-9,.column.is-offset-9-tablet{margin-left:75%}.column.is-10,.column.is-10-tablet{-webkit-box-flex:0;-ms-flex:none;flex:none;width:83.33333%}.column.is-offset-10,.column.is-offset-10-tablet{margin-left:83.33333%}.column.is-11,.column.is-11-tablet{-webkit-box-flex:0;-ms-flex:none;flex:none;width:91.66667%}.column.is-offset-11,.column.is-offset-11-tablet{margin-left:91.66667%}.column.is-12,.column.is-12-tablet{-webkit-box-flex:0;-ms-flex:none;flex:none;width:100%}.column.is-offset-12,.column.is-offset-12-tablet{margin-left:100%}}@media screen and (max-width:1023px){.column.is-narrow-touch{-webkit-box-flex:0;-ms-flex:none;flex:none}.column.is-full-touch{-webkit-box-flex:0;-ms-flex:none;flex:none;width:100%}.column.is-three-quarters-touch{-webkit-box-flex:0;-ms-flex:none;flex:none;width:75%}.column.is-two-thirds-touch{-webkit-box-flex:0;-ms-flex:none;flex:none;width:66.6666%}.column.is-half-touch{-webkit-box-flex:0;-ms-flex:none;flex:none;width:50%}.column.is-one-third-touch{-webkit-box-flex:0;-ms-flex:none;flex:none;width:33.3333%}.column.is-one-quarter-touch{-webkit-box-flex:0;-ms-flex:none;flex:none;width:25%}.column.is-one-fifth-touch{-webkit-box-flex:0;-ms-flex:none;flex:none;width:20%}.column.is-two-fifths-touch{-webkit-box-flex:0;-ms-flex:none;flex:none;width:40%}.column.is-three-fifths-touch{-webkit-box-flex:0;-ms-flex:none;flex:none;width:60%}.column.is-four-fifths-touch{-webkit-box-flex:0;-ms-flex:none;flex:none;width:80%}.column.is-offset-three-quarters-touch{margin-left:75%}.column.is-offset-two-thirds-touch{margin-left:66.6666%}.column.is-offset-half-touch{margin-left:50%}.column.is-offset-one-third-touch{margin-left:33.3333%}.column.is-offset-one-quarter-touch{margin-left:25%}.column.is-offset-one-fifth-touch{margin-left:20%}.column.is-offset-two-fifths-touch{margin-left:40%}.column.is-offset-three-fifths-touch{margin-left:60%}.column.is-offset-four-fifths-touch{margin-left:80%}.column.is-1-touch{-webkit-box-flex:0;-ms-flex:none;flex:none;width:8.33333%}.column.is-offset-1-touch{margin-left:8.33333%}.column.is-2-touch{-webkit-box-flex:0;-ms-flex:none;flex:none;width:16.66667%}.column.is-offset-2-touch{margin-left:16.66667%}.column.is-3-touch{-webkit-box-flex:0;-ms-flex:none;flex:none;width:25%}.column.is-offset-3-touch{margin-left:25%}.column.is-4-touch{-webkit-box-flex:0;-ms-flex:none;flex:none;width:33.33333%}.column.is-offset-4-touch{margin-left:33.33333%}.column.is-5-touch{-webkit-box-flex:0;-ms-flex:none;flex:none;width:41.66667%}.column.is-offset-5-touch{margin-left:41.66667%}.column.is-6-touch{-webkit-box-flex:0;-ms-flex:none;flex:none;width:50%}.column.is-offset-6-touch{margin-left:50%}.column.is-7-touch{-webkit-box-flex:0;-ms-flex:none;flex:none;width:58.33333%}.column.is-offset-7-touch{margin-left:58.33333%}.column.is-8-touch{-webkit-box-flex:0;-ms-flex:none;flex:none;width:66.66667%}.column.is-offset-8-touch{margin-left:66.66667%}.column.is-9-touch{-webkit-box-flex:0;-ms-flex:none;flex:none;width:75%}.column.is-offset-9-touch{margin-left:75%}.column.is-10-touch{-webkit-box-flex:0;-ms-flex:none;flex:none;width:83.33333%}.column.is-offset-10-touch{margin-left:83.33333%}.column.is-11-touch{-webkit-box-flex:0;-ms-flex:none;flex:none;width:91.66667%}.column.is-offset-11-touch{margin-left:91.66667%}.column.is-12-touch{-webkit-box-flex:0;-ms-flex:none;flex:none;width:100%}.column.is-offset-12-touch{margin-left:100%}}@media screen and (min-width:1024px){.column.is-narrow-desktop{-webkit-box-flex:0;-ms-flex:none;flex:none}.column.is-full-desktop{-webkit-box-flex:0;-ms-flex:none;flex:none;width:100%}.column.is-three-quarters-desktop{-webkit-box-flex:0;-ms-flex:none;flex:none;width:75%}.column.is-two-thirds-desktop{-webkit-box-flex:0;-ms-flex:none;flex:none;width:66.6666%}.column.is-half-desktop{-webkit-box-flex:0;-ms-flex:none;flex:none;width:50%}.column.is-one-third-desktop{-webkit-box-flex:0;-ms-flex:none;flex:none;width:33.3333%}.column.is-one-quarter-desktop{-webkit-box-flex:0;-ms-flex:none;flex:none;width:25%}.column.is-one-fifth-desktop{-webkit-box-flex:0;-ms-flex:none;flex:none;width:20%}.column.is-two-fifths-desktop{-webkit-box-flex:0;-ms-flex:none;flex:none;width:40%}.column.is-three-fifths-desktop{-webkit-box-flex:0;-ms-flex:none;flex:none;width:60%}.column.is-four-fifths-desktop{-webkit-box-flex:0;-ms-flex:none;flex:none;width:80%}.column.is-offset-three-quarters-desktop{margin-left:75%}.column.is-offset-two-thirds-desktop{margin-left:66.6666%}.column.is-offset-half-desktop{margin-left:50%}.column.is-offset-one-third-desktop{margin-left:33.3333%}.column.is-offset-one-quarter-desktop{margin-left:25%}.column.is-offset-one-fifth-desktop{margin-left:20%}.column.is-offset-two-fifths-desktop{margin-left:40%}.column.is-offset-three-fifths-desktop{margin-left:60%}.column.is-offset-four-fifths-desktop{margin-left:80%}.column.is-1-desktop{-webkit-box-flex:0;-ms-flex:none;flex:none;width:8.33333%}.column.is-offset-1-desktop{margin-left:8.33333%}.column.is-2-desktop{-webkit-box-flex:0;-ms-flex:none;flex:none;width:16.66667%}.column.is-offset-2-desktop{margin-left:16.66667%}.column.is-3-desktop{-webkit-box-flex:0;-ms-flex:none;flex:none;width:25%}.column.is-offset-3-desktop{margin-left:25%}.column.is-4-desktop{-webkit-box-flex:0;-ms-flex:none;flex:none;width:33.33333%}.column.is-offset-4-desktop{margin-left:33.33333%}.column.is-5-desktop{-webkit-box-flex:0;-ms-flex:none;flex:none;width:41.66667%}.column.is-offset-5-desktop{margin-left:41.66667%}.column.is-6-desktop{-webkit-box-flex:0;-ms-flex:none;flex:none;width:50%}.column.is-offset-6-desktop{margin-left:50%}.column.is-7-desktop{-webkit-box-flex:0;-ms-flex:none;flex:none;width:58.33333%}.column.is-offset-7-desktop{margin-left:58.33333%}.column.is-8-desktop{-webkit-box-flex:0;-ms-flex:none;flex:none;width:66.66667%}.column.is-offset-8-desktop{margin-left:66.66667%}.column.is-9-desktop{-webkit-box-flex:0;-ms-flex:none;flex:none;width:75%}.column.is-offset-9-desktop{margin-left:75%}.column.is-10-desktop{-webkit-box-flex:0;-ms-flex:none;flex:none;width:83.33333%}.column.is-offset-10-desktop{margin-left:83.33333%}.column.is-11-desktop{-webkit-box-flex:0;-ms-flex:none;flex:none;width:91.66667%}.column.is-offset-11-desktop{margin-left:91.66667%}.column.is-12-desktop{-webkit-box-flex:0;-ms-flex:none;flex:none;width:100%}.column.is-offset-12-desktop{margin-left:100%}}@media screen and (min-width:1216px){.column.is-narrow-widescreen{-webkit-box-flex:0;-ms-flex:none;flex:none}.column.is-full-widescreen{-webkit-box-flex:0;-ms-flex:none;flex:none;width:100%}.column.is-three-quarters-widescreen{-webkit-box-flex:0;-ms-flex:none;flex:none;width:75%}.column.is-two-thirds-widescreen{-webkit-box-flex:0;-ms-flex:none;flex:none;width:66.6666%}.column.is-half-widescreen{-webkit-box-flex:0;-ms-flex:none;flex:none;width:50%}.column.is-one-third-widescreen{-webkit-box-flex:0;-ms-flex:none;flex:none;width:33.3333%}.column.is-one-quarter-widescreen{-webkit-box-flex:0;-ms-flex:none;flex:none;width:25%}.column.is-one-fifth-widescreen{-webkit-box-flex:0;-ms-flex:none;flex:none;width:20%}.column.is-two-fifths-widescreen{-webkit-box-flex:0;-ms-flex:none;flex:none;width:40%}.column.is-three-fifths-widescreen{-webkit-box-flex:0;-ms-flex:none;flex:none;width:60%}.column.is-four-fifths-widescreen{-webkit-box-flex:0;-ms-flex:none;flex:none;width:80%}.column.is-offset-three-quarters-widescreen{margin-left:75%}.column.is-offset-two-thirds-widescreen{margin-left:66.6666%}.column.is-offset-half-widescreen{margin-left:50%}.column.is-offset-one-third-widescreen{margin-left:33.3333%}.column.is-offset-one-quarter-widescreen{margin-left:25%}.column.is-offset-one-fifth-widescreen{margin-left:20%}.column.is-offset-two-fifths-widescreen{margin-left:40%}.column.is-offset-three-fifths-widescreen{margin-left:60%}.column.is-offset-four-fifths-widescreen{margin-left:80%}.column.is-1-widescreen{-webkit-box-flex:0;-ms-flex:none;flex:none;width:8.33333%}.column.is-offset-1-widescreen{margin-left:8.33333%}.column.is-2-widescreen{-webkit-box-flex:0;-ms-flex:none;flex:none;width:16.66667%}.column.is-offset-2-widescreen{margin-left:16.66667%}.column.is-3-widescreen{-webkit-box-flex:0;-ms-flex:none;flex:none;width:25%}.column.is-offset-3-widescreen{margin-left:25%}.column.is-4-widescreen{-webkit-box-flex:0;-ms-flex:none;flex:none;width:33.33333%}.column.is-offset-4-widescreen{margin-left:33.33333%}.column.is-5-widescreen{-webkit-box-flex:0;-ms-flex:none;flex:none;width:41.66667%}.column.is-offset-5-widescreen{margin-left:41.66667%}.column.is-6-widescreen{-webkit-box-flex:0;-ms-flex:none;flex:none;width:50%}.column.is-offset-6-widescreen{margin-left:50%}.column.is-7-widescreen{-webkit-box-flex:0;-ms-flex:none;flex:none;width:58.33333%}.column.is-offset-7-widescreen{margin-left:58.33333%}.column.is-8-widescreen{-webkit-box-flex:0;-ms-flex:none;flex:none;width:66.66667%}.column.is-offset-8-widescreen{margin-left:66.66667%}.column.is-9-widescreen{-webkit-box-flex:0;-ms-flex:none;flex:none;width:75%}.column.is-offset-9-widescreen{margin-left:75%}.column.is-10-widescreen{-webkit-box-flex:0;-ms-flex:none;flex:none;width:83.33333%}.column.is-offset-10-widescreen{margin-left:83.33333%}.column.is-11-widescreen{-webkit-box-flex:0;-ms-flex:none;flex:none;width:91.66667%}.column.is-offset-11-widescreen{margin-left:91.66667%}.column.is-12-widescreen{-webkit-box-flex:0;-ms-flex:none;flex:none;width:100%}.column.is-offset-12-widescreen{margin-left:100%}}@media screen and (min-width:1408px){.column.is-narrow-fullhd{-webkit-box-flex:0;-ms-flex:none;flex:none}.column.is-full-fullhd{-webkit-box-flex:0;-ms-flex:none;flex:none;width:100%}.column.is-three-quarters-fullhd{-webkit-box-flex:0;-ms-flex:none;flex:none;width:75%}.column.is-two-thirds-fullhd{-webkit-box-flex:0;-ms-flex:none;flex:none;width:66.6666%}.column.is-half-fullhd{-webkit-box-flex:0;-ms-flex:none;flex:none;width:50%}.column.is-one-third-fullhd{-webkit-box-flex:0;-ms-flex:none;flex:none;width:33.3333%}.column.is-one-quarter-fullhd{-webkit-box-flex:0;-ms-flex:none;flex:none;width:25%}.column.is-one-fifth-fullhd{-webkit-box-flex:0;-ms-flex:none;flex:none;width:20%}.column.is-two-fifths-fullhd{-webkit-box-flex:0;-ms-flex:none;flex:none;width:40%}.column.is-three-fifths-fullhd{-webkit-box-flex:0;-ms-flex:none;flex:none;width:60%}.column.is-four-fifths-fullhd{-webkit-box-flex:0;-ms-flex:none;flex:none;width:80%}.column.is-offset-three-quarters-fullhd{margin-left:75%}.column.is-offset-two-thirds-fullhd{margin-left:66.6666%}.column.is-offset-half-fullhd{margin-left:50%}.column.is-offset-one-third-fullhd{margin-left:33.3333%}.column.is-offset-one-quarter-fullhd{margin-left:25%}.column.is-offset-one-fifth-fullhd{margin-left:20%}.column.is-offset-two-fifths-fullhd{margin-left:40%}.column.is-offset-three-fifths-fullhd{margin-left:60%}.column.is-offset-four-fifths-fullhd{margin-left:80%}.column.is-1-fullhd{-webkit-box-flex:0;-ms-flex:none;flex:none;width:8.33333%}.column.is-offset-1-fullhd{margin-left:8.33333%}.column.is-2-fullhd{-webkit-box-flex:0;-ms-flex:none;flex:none;width:16.66667%}.column.is-offset-2-fullhd{margin-left:16.66667%}.column.is-3-fullhd{-webkit-box-flex:0;-ms-flex:none;flex:none;width:25%}.column.is-offset-3-fullhd{margin-left:25%}.column.is-4-fullhd{-webkit-box-flex:0;-ms-flex:none;flex:none;width:33.33333%}.column.is-offset-4-fullhd{margin-left:33.33333%}.column.is-5-fullhd{-webkit-box-flex:0;-ms-flex:none;flex:none;width:41.66667%}.column.is-offset-5-fullhd{margin-left:41.66667%}.column.is-6-fullhd{-webkit-box-flex:0;-ms-flex:none;flex:none;width:50%}.column.is-offset-6-fullhd{margin-left:50%}.column.is-7-fullhd{-webkit-box-flex:0;-ms-flex:none;flex:none;width:58.33333%}.column.is-offset-7-fullhd{margin-left:58.33333%}.column.is-8-fullhd{-webkit-box-flex:0;-ms-flex:none;flex:none;width:66.66667%}.column.is-offset-8-fullhd{margin-left:66.66667%}.column.is-9-fullhd{-webkit-box-flex:0;-ms-flex:none;flex:none;width:75%}.column.is-offset-9-fullhd{margin-left:75%}.column.is-10-fullhd{-webkit-box-flex:0;-ms-flex:none;flex:none;width:83.33333%}.column.is-offset-10-fullhd{margin-left:83.33333%}.column.is-11-fullhd{-webkit-box-flex:0;-ms-flex:none;flex:none;width:91.66667%}.column.is-offset-11-fullhd{margin-left:91.66667%}.column.is-12-fullhd{-webkit-box-flex:0;-ms-flex:none;flex:none;width:100%}.column.is-offset-12-fullhd{margin-left:100%}}.columns{margin-left:-.75rem;margin-right:-.75rem;margin-top:-.75rem}.columns:last-child{margin-bottom:-.75rem}.columns:not(:last-child){margin-bottom:calc(1.5rem - .75rem)}.columns.is-centered{-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center}.columns.is-gapless{margin-left:0;margin-right:0;margin-top:0}.columns.is-gapless>.column{margin:0;padding:0!important}.columns.is-gapless:not(:last-child){margin-bottom:1.5rem}.columns.is-gapless:last-child{margin-bottom:0}.columns.is-mobile{display:-webkit-box;display:-ms-flexbox;display:flex}.columns.is-multiline{-ms-flex-wrap:wrap;flex-wrap:wrap}.columns.is-vcentered{-webkit-box-align:center;-ms-flex-align:center;align-items:center}@media screen and (min-width:769px),print{.columns:not(.is-desktop){display:-webkit-box;display:-ms-flexbox;display:flex}}@media screen and (min-width:1024px){.columns.is-desktop{display:-webkit-box;display:-ms-flexbox;display:flex}}.columns.is-variable{--columnGap:0.75rem;margin-left:calc(-1 * var(--columnGap));margin-right:calc(-1 * var(--columnGap))}.columns.is-variable .column{padding-left:var(--columnGap);padding-right:var(--columnGap)}.columns.is-variable.is-0{--columnGap:0rem}.columns.is-variable.is-1{--columnGap:0.25rem}.columns.is-variable.is-2{--columnGap:0.5rem}.columns.is-variable.is-3{--columnGap:0.75rem}.columns.is-variable.is-4{--columnGap:1rem}.columns.is-variable.is-5{--columnGap:1.25rem}.columns.is-variable.is-6{--columnGap:1.5rem}.columns.is-variable.is-7{--columnGap:1.75rem}.columns.is-variable.is-8{--columnGap:2rem}.tile{-webkit-box-align:stretch;-ms-flex-align:stretch;align-items:stretch;display:block;-ms-flex-preferred-size:0;flex-basis:0;-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;-ms-flex-negative:1;flex-shrink:1;min-height:-webkit-min-content;min-height:-moz-min-content;min-height:min-content}.tile.is-ancestor{margin-left:-.75rem;margin-right:-.75rem;margin-top:-.75rem}.tile.is-ancestor:last-child{margin-bottom:-.75rem}.tile.is-ancestor:not(:last-child){margin-bottom:.75rem}.tile.is-child{margin:0!important}.tile.is-parent{padding:.75rem}.tile.is-vertical{-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column}.tile.is-vertical>.tile.is-child:not(:last-child){margin-bottom:1.5rem!important}@media screen and (min-width:769px),print{.tile:not(.is-child){display:-webkit-box;display:-ms-flexbox;display:flex}.tile.is-1{-webkit-box-flex:0;-ms-flex:none;flex:none;width:8.33333%}.tile.is-2{-webkit-box-flex:0;-ms-flex:none;flex:none;width:16.66667%}.tile.is-3{-webkit-box-flex:0;-ms-flex:none;flex:none;width:25%}.tile.is-4{-webkit-box-flex:0;-ms-flex:none;flex:none;width:33.33333%}.tile.is-5{-webkit-box-flex:0;-ms-flex:none;flex:none;width:41.66667%}.tile.is-6{-webkit-box-flex:0;-ms-flex:none;flex:none;width:50%}.tile.is-7{-webkit-box-flex:0;-ms-flex:none;flex:none;width:58.33333%}.tile.is-8{-webkit-box-flex:0;-ms-flex:none;flex:none;width:66.66667%}.tile.is-9{-webkit-box-flex:0;-ms-flex:none;flex:none;width:75%}.tile.is-10{-webkit-box-flex:0;-ms-flex:none;flex:none;width:83.33333%}.tile.is-11{-webkit-box-flex:0;-ms-flex:none;flex:none;width:91.66667%}.tile.is-12{-webkit-box-flex:0;-ms-flex:none;flex:none;width:100%}}.hero{-webkit-box-align:stretch;-ms-flex-align:stretch;align-items:stretch;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between}.hero .navbar{background:0 0}.hero .tabs ul{border-bottom:none}.hero.is-white{background-color:#fff;color:#0a0a0a}.hero.is-white a:not(.button):not(.dropdown-item):not(.tag),.hero.is-white strong{color:inherit}.hero.is-white .title{color:#0a0a0a}.hero.is-white .subtitle{color:rgba(10,10,10,.9)}.hero.is-white .subtitle a:not(.button),.hero.is-white .subtitle strong{color:#0a0a0a}@media screen and (max-width:1023px){.hero.is-white .navbar-menu{background-color:#fff}}.hero.is-white .navbar-item,.hero.is-white .navbar-link{color:rgba(10,10,10,.7)}.hero.is-white .navbar-link.is-active,.hero.is-white .navbar-link:hover,.hero.is-white a.navbar-item.is-active,.hero.is-white a.navbar-item:hover{background-color:#f2f2f2;color:#0a0a0a}.hero.is-white .tabs a{color:#0a0a0a;opacity:.9}.hero.is-white .tabs a:hover{opacity:1}.hero.is-white .tabs li.is-active a{opacity:1}.hero.is-white .tabs.is-boxed a,.hero.is-white .tabs.is-toggle a{color:#0a0a0a}.hero.is-white .tabs.is-boxed a:hover,.hero.is-white .tabs.is-toggle a:hover{background-color:rgba(10,10,10,.1)}.hero.is-white .tabs.is-boxed li.is-active a,.hero.is-white .tabs.is-boxed li.is-active a:hover,.hero.is-white .tabs.is-toggle li.is-active a,.hero.is-white .tabs.is-toggle li.is-active a:hover{background-color:#0a0a0a;border-color:#0a0a0a;color:#fff}.hero.is-white.is-bold{background-image:linear-gradient(141deg,#e6e6e6 0,#fff 71%,#fff 100%)}@media screen and (max-width:768px){.hero.is-white.is-bold .navbar-menu{background-image:linear-gradient(141deg,#e6e6e6 0,#fff 71%,#fff 100%)}}.hero.is-black{background-color:#0a0a0a;color:#fff}.hero.is-black a:not(.button):not(.dropdown-item):not(.tag),.hero.is-black strong{color:inherit}.hero.is-black .title{color:#fff}.hero.is-black .subtitle{color:rgba(255,255,255,.9)}.hero.is-black .subtitle a:not(.button),.hero.is-black .subtitle strong{color:#fff}@media screen and (max-width:1023px){.hero.is-black .navbar-menu{background-color:#0a0a0a}}.hero.is-black .navbar-item,.hero.is-black .navbar-link{color:rgba(255,255,255,.7)}.hero.is-black .navbar-link.is-active,.hero.is-black .navbar-link:hover,.hero.is-black a.navbar-item.is-active,.hero.is-black a.navbar-item:hover{background-color:#000;color:#fff}.hero.is-black .tabs a{color:#fff;opacity:.9}.hero.is-black .tabs a:hover{opacity:1}.hero.is-black .tabs li.is-active a{opacity:1}.hero.is-black .tabs.is-boxed a,.hero.is-black .tabs.is-toggle a{color:#fff}.hero.is-black .tabs.is-boxed a:hover,.hero.is-black .tabs.is-toggle a:hover{background-color:rgba(10,10,10,.1)}.hero.is-black .tabs.is-boxed li.is-active a,.hero.is-black .tabs.is-boxed li.is-active a:hover,.hero.is-black .tabs.is-toggle li.is-active a,.hero.is-black .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#0a0a0a}.hero.is-black.is-bold{background-image:linear-gradient(141deg,#000 0,#0a0a0a 71%,#181616 100%)}@media screen and (max-width:768px){.hero.is-black.is-bold .navbar-menu{background-image:linear-gradient(141deg,#000 0,#0a0a0a 71%,#181616 100%)}}.hero.is-light{background-color:#f5f5f5;color:#363636}.hero.is-light a:not(.button):not(.dropdown-item):not(.tag),.hero.is-light strong{color:inherit}.hero.is-light .title{color:#363636}.hero.is-light .subtitle{color:rgba(54,54,54,.9)}.hero.is-light .subtitle a:not(.button),.hero.is-light .subtitle strong{color:#363636}@media screen and (max-width:1023px){.hero.is-light .navbar-menu{background-color:#f5f5f5}}.hero.is-light .navbar-item,.hero.is-light .navbar-link{color:rgba(54,54,54,.7)}.hero.is-light .navbar-link.is-active,.hero.is-light .navbar-link:hover,.hero.is-light a.navbar-item.is-active,.hero.is-light a.navbar-item:hover{background-color:#e8e8e8;color:#363636}.hero.is-light .tabs a{color:#363636;opacity:.9}.hero.is-light .tabs a:hover{opacity:1}.hero.is-light .tabs li.is-active a{opacity:1}.hero.is-light .tabs.is-boxed a,.hero.is-light .tabs.is-toggle a{color:#363636}.hero.is-light .tabs.is-boxed a:hover,.hero.is-light .tabs.is-toggle a:hover{background-color:rgba(10,10,10,.1)}.hero.is-light .tabs.is-boxed li.is-active a,.hero.is-light .tabs.is-boxed li.is-active a:hover,.hero.is-light .tabs.is-toggle li.is-active a,.hero.is-light .tabs.is-toggle li.is-active a:hover{background-color:#363636;border-color:#363636;color:#f5f5f5}.hero.is-light.is-bold{background-image:linear-gradient(141deg,#dfd8d9 0,#f5f5f5 71%,#fff 100%)}@media screen and (max-width:768px){.hero.is-light.is-bold .navbar-menu{background-image:linear-gradient(141deg,#dfd8d9 0,#f5f5f5 71%,#fff 100%)}}.hero.is-dark{background-color:#363636;color:#f5f5f5}.hero.is-dark a:not(.button):not(.dropdown-item):not(.tag),.hero.is-dark strong{color:inherit}.hero.is-dark .title{color:#f5f5f5}.hero.is-dark .subtitle{color:rgba(245,245,245,.9)}.hero.is-dark .subtitle a:not(.button),.hero.is-dark .subtitle strong{color:#f5f5f5}@media screen and (max-width:1023px){.hero.is-dark .navbar-menu{background-color:#363636}}.hero.is-dark .navbar-item,.hero.is-dark .navbar-link{color:rgba(245,245,245,.7)}.hero.is-dark .navbar-link.is-active,.hero.is-dark .navbar-link:hover,.hero.is-dark a.navbar-item.is-active,.hero.is-dark a.navbar-item:hover{background-color:#292929;color:#f5f5f5}.hero.is-dark .tabs a{color:#f5f5f5;opacity:.9}.hero.is-dark .tabs a:hover{opacity:1}.hero.is-dark .tabs li.is-active a{opacity:1}.hero.is-dark .tabs.is-boxed a,.hero.is-dark .tabs.is-toggle a{color:#f5f5f5}.hero.is-dark .tabs.is-boxed a:hover,.hero.is-dark .tabs.is-toggle a:hover{background-color:rgba(10,10,10,.1)}.hero.is-dark .tabs.is-boxed li.is-active a,.hero.is-dark .tabs.is-boxed li.is-active a:hover,.hero.is-dark .tabs.is-toggle li.is-active a,.hero.is-dark .tabs.is-toggle li.is-active a:hover{background-color:#f5f5f5;border-color:#f5f5f5;color:#363636}.hero.is-dark.is-bold{background-image:linear-gradient(141deg,#1f191a 0,#363636 71%,#46403f 100%)}@media screen and (max-width:768px){.hero.is-dark.is-bold .navbar-menu{background-image:linear-gradient(141deg,#1f191a 0,#363636 71%,#46403f 100%)}}.hero.is-primary{background-color:#00d1b2;color:#fff}.hero.is-primary a:not(.button):not(.dropdown-item):not(.tag),.hero.is-primary strong{color:inherit}.hero.is-primary .title{color:#fff}.hero.is-primary .subtitle{color:rgba(255,255,255,.9)}.hero.is-primary .subtitle a:not(.button),.hero.is-primary .subtitle strong{color:#fff}@media screen and (max-width:1023px){.hero.is-primary .navbar-menu{background-color:#00d1b2}}.hero.is-primary .navbar-item,.hero.is-primary .navbar-link{color:rgba(255,255,255,.7)}.hero.is-primary .navbar-link.is-active,.hero.is-primary .navbar-link:hover,.hero.is-primary a.navbar-item.is-active,.hero.is-primary a.navbar-item:hover{background-color:#00b89c;color:#fff}.hero.is-primary .tabs a{color:#fff;opacity:.9}.hero.is-primary .tabs a:hover{opacity:1}.hero.is-primary .tabs li.is-active a{opacity:1}.hero.is-primary .tabs.is-boxed a,.hero.is-primary .tabs.is-toggle a{color:#fff}.hero.is-primary .tabs.is-boxed a:hover,.hero.is-primary .tabs.is-toggle a:hover{background-color:rgba(10,10,10,.1)}.hero.is-primary .tabs.is-boxed li.is-active a,.hero.is-primary .tabs.is-boxed li.is-active a:hover,.hero.is-primary .tabs.is-toggle li.is-active a,.hero.is-primary .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#00d1b2}.hero.is-primary.is-bold{background-image:linear-gradient(141deg,#009e6c 0,#00d1b2 71%,#00e7eb 100%)}@media screen and (max-width:768px){.hero.is-primary.is-bold .navbar-menu{background-image:linear-gradient(141deg,#009e6c 0,#00d1b2 71%,#00e7eb 100%)}}.hero.is-link{background-color:#3273dc;color:#fff}.hero.is-link a:not(.button):not(.dropdown-item):not(.tag),.hero.is-link strong{color:inherit}.hero.is-link .title{color:#fff}.hero.is-link .subtitle{color:rgba(255,255,255,.9)}.hero.is-link .subtitle a:not(.button),.hero.is-link .subtitle strong{color:#fff}@media screen and (max-width:1023px){.hero.is-link .navbar-menu{background-color:#3273dc}}.hero.is-link .navbar-item,.hero.is-link .navbar-link{color:rgba(255,255,255,.7)}.hero.is-link .navbar-link.is-active,.hero.is-link .navbar-link:hover,.hero.is-link a.navbar-item.is-active,.hero.is-link a.navbar-item:hover{background-color:#2366d1;color:#fff}.hero.is-link .tabs a{color:#fff;opacity:.9}.hero.is-link .tabs a:hover{opacity:1}.hero.is-link .tabs li.is-active a{opacity:1}.hero.is-link .tabs.is-boxed a,.hero.is-link .tabs.is-toggle a{color:#fff}.hero.is-link .tabs.is-boxed a:hover,.hero.is-link .tabs.is-toggle a:hover{background-color:rgba(10,10,10,.1)}.hero.is-link .tabs.is-boxed li.is-active a,.hero.is-link .tabs.is-boxed li.is-active a:hover,.hero.is-link .tabs.is-toggle li.is-active a,.hero.is-link .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#3273dc}.hero.is-link.is-bold{background-image:linear-gradient(141deg,#1577c6 0,#3273dc 71%,#4366e5 100%)}@media screen and (max-width:768px){.hero.is-link.is-bold .navbar-menu{background-image:linear-gradient(141deg,#1577c6 0,#3273dc 71%,#4366e5 100%)}}.hero.is-info{background-color:#209cee;color:#fff}.hero.is-info a:not(.button):not(.dropdown-item):not(.tag),.hero.is-info strong{color:inherit}.hero.is-info .title{color:#fff}.hero.is-info .subtitle{color:rgba(255,255,255,.9)}.hero.is-info .subtitle a:not(.button),.hero.is-info .subtitle strong{color:#fff}@media screen and (max-width:1023px){.hero.is-info .navbar-menu{background-color:#209cee}}.hero.is-info .navbar-item,.hero.is-info .navbar-link{color:rgba(255,255,255,.7)}.hero.is-info .navbar-link.is-active,.hero.is-info .navbar-link:hover,.hero.is-info a.navbar-item.is-active,.hero.is-info a.navbar-item:hover{background-color:#118fe4;color:#fff}.hero.is-info .tabs a{color:#fff;opacity:.9}.hero.is-info .tabs a:hover{opacity:1}.hero.is-info .tabs li.is-active a{opacity:1}.hero.is-info .tabs.is-boxed a,.hero.is-info .tabs.is-toggle a{color:#fff}.hero.is-info .tabs.is-boxed a:hover,.hero.is-info .tabs.is-toggle a:hover{background-color:rgba(10,10,10,.1)}.hero.is-info .tabs.is-boxed li.is-active a,.hero.is-info .tabs.is-boxed li.is-active a:hover,.hero.is-info .tabs.is-toggle li.is-active a,.hero.is-info .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#209cee}.hero.is-info.is-bold{background-image:linear-gradient(141deg,#04a6d7 0,#209cee 71%,#3287f5 100%)}@media screen and (max-width:768px){.hero.is-info.is-bold .navbar-menu{background-image:linear-gradient(141deg,#04a6d7 0,#209cee 71%,#3287f5 100%)}}.hero.is-success{background-color:#23d160;color:#fff}.hero.is-success a:not(.button):not(.dropdown-item):not(.tag),.hero.is-success strong{color:inherit}.hero.is-success .title{color:#fff}.hero.is-success .subtitle{color:rgba(255,255,255,.9)}.hero.is-success .subtitle a:not(.button),.hero.is-success .subtitle strong{color:#fff}@media screen and (max-width:1023px){.hero.is-success .navbar-menu{background-color:#23d160}}.hero.is-success .navbar-item,.hero.is-success .navbar-link{color:rgba(255,255,255,.7)}.hero.is-success .navbar-link.is-active,.hero.is-success .navbar-link:hover,.hero.is-success a.navbar-item.is-active,.hero.is-success a.navbar-item:hover{background-color:#20bc56;color:#fff}.hero.is-success .tabs a{color:#fff;opacity:.9}.hero.is-success .tabs a:hover{opacity:1}.hero.is-success .tabs li.is-active a{opacity:1}.hero.is-success .tabs.is-boxed a,.hero.is-success .tabs.is-toggle a{color:#fff}.hero.is-success .tabs.is-boxed a:hover,.hero.is-success .tabs.is-toggle a:hover{background-color:rgba(10,10,10,.1)}.hero.is-success .tabs.is-boxed li.is-active a,.hero.is-success .tabs.is-boxed li.is-active a:hover,.hero.is-success .tabs.is-toggle li.is-active a,.hero.is-success .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#23d160}.hero.is-success.is-bold{background-image:linear-gradient(141deg,#12af2f 0,#23d160 71%,#2ce28a 100%)}@media screen and (max-width:768px){.hero.is-success.is-bold .navbar-menu{background-image:linear-gradient(141deg,#12af2f 0,#23d160 71%,#2ce28a 100%)}}.hero.is-warning{background-color:#ffdd57;color:rgba(0,0,0,.7)}.hero.is-warning a:not(.button):not(.dropdown-item):not(.tag),.hero.is-warning strong{color:inherit}.hero.is-warning .title{color:rgba(0,0,0,.7)}.hero.is-warning .subtitle{color:rgba(0,0,0,.9)}.hero.is-warning .subtitle a:not(.button),.hero.is-warning .subtitle strong{color:rgba(0,0,0,.7)}@media screen and (max-width:1023px){.hero.is-warning .navbar-menu{background-color:#ffdd57}}.hero.is-warning .navbar-item,.hero.is-warning .navbar-link{color:rgba(0,0,0,.7)}.hero.is-warning .navbar-link.is-active,.hero.is-warning .navbar-link:hover,.hero.is-warning a.navbar-item.is-active,.hero.is-warning a.navbar-item:hover{background-color:#ffd83d;color:rgba(0,0,0,.7)}.hero.is-warning .tabs a{color:rgba(0,0,0,.7);opacity:.9}.hero.is-warning .tabs a:hover{opacity:1}.hero.is-warning .tabs li.is-active a{opacity:1}.hero.is-warning .tabs.is-boxed a,.hero.is-warning .tabs.is-toggle a{color:rgba(0,0,0,.7)}.hero.is-warning .tabs.is-boxed a:hover,.hero.is-warning .tabs.is-toggle a:hover{background-color:rgba(10,10,10,.1)}.hero.is-warning .tabs.is-boxed li.is-active a,.hero.is-warning .tabs.is-boxed li.is-active a:hover,.hero.is-warning .tabs.is-toggle li.is-active a,.hero.is-warning .tabs.is-toggle li.is-active a:hover{background-color:rgba(0,0,0,.7);border-color:rgba(0,0,0,.7);color:#ffdd57}.hero.is-warning.is-bold{background-image:linear-gradient(141deg,#ffaf24 0,#ffdd57 71%,#fffa70 100%)}@media screen and (max-width:768px){.hero.is-warning.is-bold .navbar-menu{background-image:linear-gradient(141deg,#ffaf24 0,#ffdd57 71%,#fffa70 100%)}}.hero.is-danger{background-color:#ff3860;color:#fff}.hero.is-danger a:not(.button):not(.dropdown-item):not(.tag),.hero.is-danger strong{color:inherit}.hero.is-danger .title{color:#fff}.hero.is-danger .subtitle{color:rgba(255,255,255,.9)}.hero.is-danger .subtitle a:not(.button),.hero.is-danger .subtitle strong{color:#fff}@media screen and (max-width:1023px){.hero.is-danger .navbar-menu{background-color:#ff3860}}.hero.is-danger .navbar-item,.hero.is-danger .navbar-link{color:rgba(255,255,255,.7)}.hero.is-danger .navbar-link.is-active,.hero.is-danger .navbar-link:hover,.hero.is-danger a.navbar-item.is-active,.hero.is-danger a.navbar-item:hover{background-color:#ff1f4b;color:#fff}.hero.is-danger .tabs a{color:#fff;opacity:.9}.hero.is-danger .tabs a:hover{opacity:1}.hero.is-danger .tabs li.is-active a{opacity:1}.hero.is-danger .tabs.is-boxed a,.hero.is-danger .tabs.is-toggle a{color:#fff}.hero.is-danger .tabs.is-boxed a:hover,.hero.is-danger .tabs.is-toggle a:hover{background-color:rgba(10,10,10,.1)}.hero.is-danger .tabs.is-boxed li.is-active a,.hero.is-danger .tabs.is-boxed li.is-active a:hover,.hero.is-danger .tabs.is-toggle li.is-active a,.hero.is-danger .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#ff3860}.hero.is-danger.is-bold{background-image:linear-gradient(141deg,#ff0561 0,#ff3860 71%,#ff5257 100%)}@media screen and (max-width:768px){.hero.is-danger.is-bold .navbar-menu{background-image:linear-gradient(141deg,#ff0561 0,#ff3860 71%,#ff5257 100%)}}.hero.is-small .hero-body{padding-bottom:1.5rem;padding-top:1.5rem}@media screen and (min-width:769px),print{.hero.is-medium .hero-body{padding-bottom:9rem;padding-top:9rem}}@media screen and (min-width:769px),print{.hero.is-large .hero-body{padding-bottom:18rem;padding-top:18rem}}.hero.is-fullheight .hero-body,.hero.is-halfheight .hero-body{-webkit-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-ms-flexbox;display:flex}.hero.is-fullheight .hero-body>.container,.hero.is-halfheight .hero-body>.container{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;-ms-flex-negative:1;flex-shrink:1}.hero.is-halfheight{min-height:50vh}.hero.is-fullheight{min-height:100vh}.hero-video{bottom:0;left:0;position:absolute;right:0;top:0;overflow:hidden}.hero-video video{left:50%;min-height:100%;min-width:100%;position:absolute;top:50%;-webkit-transform:translate3d(-50%,-50%,0);transform:translate3d(-50%,-50%,0)}.hero-video.is-transparent{opacity:.3}@media screen and (max-width:768px){.hero-video{display:none}}.hero-buttons{margin-top:1.5rem}@media screen and (max-width:768px){.hero-buttons .button{display:-webkit-box;display:-ms-flexbox;display:flex}.hero-buttons .button:not(:last-child){margin-bottom:.75rem}}@media screen and (min-width:769px),print{.hero-buttons{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center}.hero-buttons .button:not(:last-child){margin-right:1.5rem}}.hero-foot,.hero-head{-webkit-box-flex:0;-ms-flex-positive:0;flex-grow:0;-ms-flex-negative:0;flex-shrink:0}.hero-body{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;-ms-flex-negative:0;flex-shrink:0;padding:3rem 1.5rem}.section{padding:3rem 1.5rem}@media screen and (min-width:1024px){.section.is-medium{padding:9rem 1.5rem}.section.is-large{padding:18rem 1.5rem}}.footer{background-color:#f5f5f5;padding:3rem 1.5rem 6rem}
+/*# sourceMappingURL=bulma.min.css.map */
\ No newline at end of file
--- /dev/null
+.margin-left-s {margin-left: 10px !important;}
+.margin-left-m {margin-left: 20px !important;}
+.margin-left-l {margin-left: 30px !important;}
+.margin-left-xl {margin-left: 40px !important;}
+.margin-left-xxl {margin-left: 50px !important;}
+
+.margin-top-s {margin-top: 10px !important;}
+
+.margin-top-m {margin-top: 20px !important;}
+.margin-top-l {margin-top: 30px !important;}
+.margin-top-xl {margin-top: 40px !important;}
+.margin-top-xxl {margin-top: 50px !important;}
+
+.margin-bottom-s {margin-bottom: 10px !important;}
+.margin-bottom-m {margin-bottom: 20px !important;}
+.margin-bottom-l {margin-bottom: 30px !important;}
+.margin-bottom-xl {margin-bottom: 40px !important;}
+.margin-bottom-xxl {margin-bottom: 50px !important;}
+
+.margin-right-s {margin-right: 10px !important;}
+.margin-right-m {margin-right: 20px !important;}
+.margin-right-l {margin-right: 30px !important;}
+.margin-right-xl {margin-right: 40px !important;}
+.margin-right-xxl {margin-right: 50px !important;}
+
+.padding-left-s {padding-left: 10px !important;}
+.padding-left-m {padding-left: 20px !important;}
+.padding-left-l {padding-left: 30px !important;}
+.padding-left-xl {padding-left: 40px !important;}
+.padding-left-xxl {padding-left: 50px !important;}
+
+.padding-top-s {padding-top: 10px !important;}
+.padding-top-m {padding-top: 20px !important;}
+.padding-top-l {padding-top: 30px !important;}
+.padding-top-xl {padding-top: 40px !important;}
+.padding-top-xxl {padding-top: 50px !important;}
+
+.padding-bottom-s {padding-bottom: 10px !important;}
+.padding-bottom-m {padding-bottom: 20px !important;}
+.padding-bottom-l {padding-bottom: 30px !important;}
+.padding-bottom-xl {padding-bottom: 40px !important;}
+.padding-bottom-xxl {padding-bottom: 50px !important;}
+
+.padding-right-s {padding-right: 10px !important;}
+.padding-right-m {padding-right: 20px !important;}
+.padding-right-l {padding-right: 30px !important;}
+.padding-right-xl {padding-right: 40px !important;}
+.padding-right-xxl {padding-right: 50px !important;}
+
+.round-border {border-radius: 50% !important;}
+
+hr {
+ display: block;
+ height: 1px;
+ margin: 0 0;
+}
+
+html {
+ min-height: 100%;
+ height: 100%;
+ -webkit-tap-highlight-color:transparent;
+}
+
+body {
+ height: inherit;
+ overflow-y: auto;
+ overflow-x: hidden;
+}
+
+.is-vertical-center {
+ display: flex;
+ align-items: center;
+}
+
+#app-title {
+ text-transform: uppercase;
+}
+
+#camera_controller {
+ width: 270px;
+ height: 270px;
+ background-image: url("../res/controller_bg.png");
+ background-size: 100% 100%;
+}
+
+.mid-div {
+ margin: 20px 0 20px 0;
+}
+
+#motion_area {
+ border-radius: 50%;
+ background-color: #ffffff;
+ background-size: contain;
+ width: 100px;
+ height: 100px;
+ display: inline-block;
+ box-shadow: 0 0 5px grey;
+ /* margin-top: 85px; */
+}
+
+#camera_controller[data-state='auto_mode_on'] > #motion_area[data-state='motion_detected'] {
+ background-color: #209cee !important;
+}
+
+#camera_controller[data-state='auto_mode_on'] > #motion_area[data-state='motion_detected'] p{
+ color: #ffffff !important;
+}
+
+#camera_controller[data-state='auto_mode_on'] > #motion_area[data-state='motion_detected'] p:after{
+ content: 'Motion Detected';
+}
+
+#camera_controller[data-state='auto_mode_on'] > #motion_area[data-state='no_motion'] {
+ background-color: #ffffff !important;
+}
+
+#camera_controller[data-state='auto_mode_on'] > #motion_area[data-state='no_motion'] p{
+ color: #777 !important;
+}
+
+#camera_controller[data-state='auto_mode_on'] > #motion_area[data-state='no_motion'] p:after{
+ content: 'No\aMotion';
+ white-space: pre;
+}
+
+#camera_controller[data-state='auto_mode_off'] #motion_area {
+ background-color: #ffffff !important;
+}
+
+#camera_controller[data-state='auto_mode_off'] p{
+ color: #ccc !important;
+}
+
+#camera_controller[data-state='auto_mode_off'] p:after{
+ content: '';
+}
+
+#motion_area > p {
+ transform: translateY(50%);
+}
+
+.icon-move {
+ height: 85px;
+ width: 85px;
+}
+
+#camera_controller[data-state='auto_mode_on'] > .icon-move {
+ background-color: #ccc;
+}
+
+#camera_controller[data-state='auto_mode_off'] > .icon-move {
+ background-color: #209cee;
+}
+
+#move-left, #move-right {
+ margin-top: 10px;
+}
+
+#move-left {
+ float: left;
+ mask: url("../res/arrow_left.png") no-repeat center;
+ mask-size: 18px 30px;
+ -webkit-mask: url("../res/arrow_left.png") no-repeat center;
+ -webkit-mask-size: 18px 30px;
+}
+
+#move-right {
+ float: right;
+ mask: url("../res/arrow_right.png") no-repeat center;
+ mask-size: 18px 30px;
+ -webkit-mask: url("../res/arrow_right.png") no-repeat center;
+ -webkit-mask-size: 18px 30px;
+}
+
+#move-up {
+ mask: url("../res/arrow_up.png") no-repeat center;
+ mask-size: 30px 18px;
+ -webkit-mask: url("../res/arrow_up.png") no-repeat center;
+ -webkit-mask-size: 30px 18px;
+}
+
+#move-down {
+ mask: url("../res/arrow_down.png") no-repeat center;
+ mask-size: 30px 18px;
+ -webkit-mask: url("../res/arrow_down.png") no-repeat center;
+ -webkit-mask-size: 30px 18px;
+}
+
+#auto_mode[data-state='on'] > #auto_mode_on_text {
+ display: block;
+}
+
+#auto_mode[data-state='on'] > #auto_mode_off_text {
+ display: none;
+}
+
+#auto_mode[data-state='off'] > #auto_mode_on_text {
+ display: none;
+}
+
+#auto_mode[data-state='off'] > #auto_mode_off_text {
+ display: block;
+}
+
+#mode_name {
+ width: 200px;
+}
+
+/* slider for IE */
+input[type=range].slider.is-info::-ms-track{
+ background:#209cee!important;
+ height: 2px;
+ border-color: transparent;
+ color: transparent;
+ background-color: transparent;
+}
+
+/* slider for mozilla */
+input[type=range].slider.is-info::-moz-range-track {
+ position:relative;
+ width: 100%;
+ height: 6px;
+ background: #ccc;
+}
+
+input[type=range].slider.is-info::-moz-range-progress {
+ position:relative;
+ width: 100%;
+ height: 6px;
+ background: #209cee;
+}
+
+/* slider for chrome */
+@media screen and (-webkit-min-device-pixel-ratio:0) {
+ input[type='range'].slider.is-info {
+ overflow: hidden;
+ width: 100%;
+ -webkit-appearance: none;
+ }
+
+ input[type='range'].slider.is-info::-webkit-slider-runnable-track {
+ height: 10px;
+ -webkit-appearance: none;
+ color: #13bba4;
+ margin-top: -1px;
+ }
+
+ input[type='range'].slider.is-info::-webkit-slider-thumb {
+ box-shadow: 1080px 0 0 1080px #ccc;
+ }
+}
+
+@media only screen and (min-height: 600px) {
+ html {
+ min-width: 100%;
+ min-height: 100%;
+ width: 100%;
+ height: 100%;
+ }
+}
+
+.leftSide {
+ float: left;
+ width: 100%;
+ background-color: #fafafa;
+}
+
+.rightSide {
+ float: left;
+ width: 100%;
+}
+
+@media only screen and (orientation: landscape) and (min-height: 360px){
+ .leftSide {
+ width: 50%;
+ height: inherit;
+ }
+ .rightSide {
+ width: 50%;
+ }
+}
+
+@media only screen and (min-width: 768px) {
+ .leftSide {
+ height: auto;
+ }
+}
+
+.loader {
+ border: 3px solid #f3f3f3;
+ border-radius: 100%;
+ border-top: 3px solid #3498db;
+ width: 40px;
+ height: 40px;
+ -webkit-animation: spin 2s linear infinite; /* Safari */
+ animation: spin 2s linear infinite;
+}
+
+/* Safari */
+@-webkit-keyframes spin {
+ 0% { -webkit-transform: rotate(0deg); }
+ 100% { -webkit-transform: rotate(360deg); }
+}
+
+@keyframes spin {
+ 0% { transform: rotate(0deg); }
+ 100% { transform: rotate(360deg); }
+}
+
+.shadow-up {
+ filter: drop-shadow(0px -10px 5px #cccccc);
+ }
+
+ .shadow-down {
+ filter: drop-shadow(0px 10px 5px #cccccc);
+ }
+
+ .shadow-right {
+ filter: drop-shadow(10px 0px 5px #cccccc);
+ }
+
+ .shadow-left {
+ filter: drop-shadow(-10px 0px 5px #cccccc);
+ }
\ No newline at end of file
--- /dev/null
+<!DOCTYPE html>
+<html>
+ <head>
+ <!-- Stylesheet Template Bulma IO-->
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+ <meta http-equiv="X-UA-Compatible" content="ie=edge">
+ <title>Smart Surveillance Camera</title>
+ <link rel="stylesheet" href="css/bulma.min.css">
+ <link rel="stylesheet" href="css/bulma-switch.min.css">
+ <link rel="stylesheet" href="css/helper.css">
+ </head>
+
+ <body>
+ <!-- Action bar-->
+ <div class="columns is-marginless is-mobile" style="background-color:#fafafa;">
+ <div class="column is-narrow">
+ <figure class="image is-24x24 margin-left-s" onclick="backAction()">
+ <img src="res/board_ic_arrow_left.png">
+ </figure>
+ </div>
+ </div>
+
+ <!-- Left -->
+ <div class="dividecolumn leftSide padding-bottom-l border-right" style="background-color:#fafafa;">
+
+ <!-- Header-->
+ <div id="app-title" class="column is-mobile is-paddingless margin-left-l margin-top-s">
+ <div class="has-text-weight-bold has-text-grey-light is-size-7">Tizen IoT</div>
+ <div class="has-text-weight-bold">Smart Surveillance Camera</div>
+ </div>
+
+ <div class="columns is-mobile is-centered margin-top-m" align="center">
+ <div class="column is-narrow">
+ <div id="camera_controller" data-state="auto_mode_on">
+ <div id="move-up" class="icon-move" onclick="onMoveUpBtnClicked()"></div>
+ <div id="move-left" class="icon-move" onclick="onMoveLeftBtnClicked()"></div>
+ <div id="motion_area" align="center" data-state="no_motion">
+ <p class="is-size-10 has-text-weight-bold"></p>
+ </div>
+ <div id="move-right" class="icon-move" onclick="onMoveRightBtnClicked()"></div>
+ <div id="move-down" class="icon-move" onclick="onMoveDownBtnClicked()"></div>
+ </span>
+ </div>
+ </div>
+ </div>
+
+ </div>
+
+ <!-- Right -->
+ <div class="dividecolumn rightSide">
+ <hr class="is-hidden-tablet" />
+ <!-- Auto Mode Option -->
+ <div class="columns is-mobile is-marginless margin-left-s">
+ <div id="auto_mode" data-state="on" class="column">
+ <p id="mode_name">Auto Control Mode</p>
+ <p class="is-size-7 has-text-info" id="auto_mode_on_text">On</p>
+ <p class="is-size-7 has-text-grey-light" id="auto_mode_off_text">Off</p>
+ </div>
+ <div class="field column margin-top-s">
+ <input type="checkbox" id="auto_mode_check" name="auto_mode_check" class="switch is-rounded is-info" checked="checked" onclick="onModeBtnClicked()">
+ <label class="is-pulled-right" for="auto_mode_check"></label>
+ </div>
+ </div>
+ <hr/>
+ </div>
+ </body>
+
+ <!-- SAMSUNG CONNECT API -->
+ <script type="text/javascript" src="lib/SCPluginApi.js"></script>
+ <script type="text/javascript" src="js/capability_servoMotor.js"></script>
+ <script type="text/javascript" src="js/capability_motionSensor.js"></script>
+ <script type="text/javascript" src="js/capability_modeSwitch.js"></script>
+ <script type="text/javascript" src="js/index.js"></script>
+</html>
--- /dev/null
+/*
+ * Copyright (c) 2015 - 2017 Samsung Electronics Co., Ltd 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.
+ */
+
+var capabilityModeSwitch = {
+ 'href' : {
+ switch: "/capability/switch/main/0"
+ },
+ 'controlMode' : "on",
+
+ 'update' : function() {
+ ocfDevice.getRemoteRepresentation(this.href.switch, this.onRepresentCallback);
+ },
+
+ 'onRepresentCallback' : function(result, deviceHandle, uri, rcsJsonString) {
+ scplugin.log.debug(className, arguments.callee.name, result);
+ scplugin.log.debug(className, arguments.callee.name, uri);
+
+ if (result == "OCF_OK" || result == "OCF_RESOURCE_CHANGED" || result == "OCF_RES_ALREADY_SUBSCRIBED") {
+ capabilityModeSwitch.controlMode = rcsJsonString["power"];
+ }
+
+ if (capabilityModeSwitch.controlMode == "off") {
+ document.getElementById("auto_mode").setAttribute('data-state', 'on');
+ document.getElementById("camera_controller").setAttribute('data-state', 'auto_mode_on');
+ document.getElementById("auto_mode_check").checked = true;
+ } else {
+ document.getElementById("auto_mode").setAttribute('data-state', 'off');
+ document.getElementById("camera_controller").setAttribute('data-state', 'auto_mode_off');
+ document.getElementById("auto_mode_check").checked = false;
+ }
+ },
+
+ 'set' : function(state) {
+ scplugin.log.debug(className, arguments.callee.name, "power : " + state);
+ var setRcsJson = {};
+ setRcsJson["power"] = state;
+ ocfDevice.setRemoteRepresentation(this.href.switch, setRcsJson, this.onRepresentCallback);
+ },
+
+ 'isControllable': function() {
+ if (this.controlMode == 'on') {
+ return true;
+ } else {
+ return false;
+ }
+ },
+
+ 'modeToggle' : function() {
+ if (this.controlMode == "on") {
+ this.set("off");
+ } else {
+ this.set("on");
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd 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.
+ */
+
+var capabilityMotionSensor = {
+ 'href' : {
+ motion: "/capability/motionSensor/main/0"
+ },
+
+ 'update' : function() {
+ ocfDevice.getRemoteRepresentation(this.href.motion, this.onRepresentCallback);
+ },
+
+ 'onRepresentCallback' : function(result, deviceHandle, uri, rcsJsonString) {
+ scplugin.log.debug(className, arguments.callee.name, result);
+ scplugin.log.debug(className, arguments.callee.name, uri);
+
+ if (result == "OCF_OK" || result == "OCF_RESOURCE_CHANGED" || result == "OCF_RES_ALREADY_SUBSCRIBED") {
+ if(rcsJsonString["value"] === undefined) return;
+
+ var state = rcsJsonString["value"];
+
+ if (state)
+ document.getElementById("motion_area").setAttribute('data-state', 'motion_detected');
+ else
+ document.getElementById("motion_area").setAttribute('data-state', 'no_motion');
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd 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.
+ */
+
+const SERVO_RANGE = {
+ VERTICAL: {
+ MIN: 15,
+ MAX: 65
+ },
+ HORIZONTAL: {
+ MIN: 5,
+ MAX: 65
+ }
+};
+const SERVO_STEP = {
+ VERTICAL: (SERVO_RANGE.VERTICAL.MAX - SERVO_RANGE.VERTICAL.MIN) / 10,
+ HORIZONTAL: (SERVO_RANGE.HORIZONTAL.MAX - SERVO_RANGE.HORIZONTAL.MIN) / 10,
+};
+const CONTROL_TYPE_VERTICAL = "vertical";
+const CONTROL_TYPE_HORIZONTAL = "horizontal";
+
+var capabilityServoMotor = {
+ 'href' : {
+ v: "/capability/audioVolume/main/0",
+ h: "/capability/switchLevel/main/0"
+ },
+ 'valueV' : 50,
+ 'valueH' : 50,
+
+ 'update' : function() {
+ for (var item in this.href) {
+ ocfDevice.getRemoteRepresentation(this.href[item], this.onRepresentCallback);
+ }
+ },
+
+ 'onRepresentCallback' : function(result, deviceHandle, uri, rcsJsonString) {
+ scplugin.log.debug(className, arguments.callee.name, result);
+ scplugin.log.debug(className, arguments.callee.name, uri);
+
+ if (result == "OCF_OK" || result == "OCF_RESOURCE_CHANGED" || result == "OCF_RES_ALREADY_SUBSCRIBED") {
+ if (uri == capabilityServoMotor.href.v) {
+ if(rcsJsonString["volume"] === undefined) return;
+ capabilityServoMotor.valueV = rcsJsonString["volume"];
+ } else if (uri == capabilityServoMotor.href.h) {
+ if(rcsJsonString["dimmingSetting"] === undefined) return;
+ capabilityServoMotor.valueH = rcsJsonString["dimmingSetting"];
+ }
+ }
+ },
+
+ 'move' : function(type, value) {
+ var setRcsJson = {};
+ var href;
+ scplugin.log.debug(className, arguments.callee.name, "Servo Motor type: " + type, "value: " + value);
+
+ if (type == CONTROL_TYPE_VERTICAL) {
+ setRcsJson["volume"] = value;
+ href = this.href.v;
+ } else if (type == CONTROL_TYPE_HORIZONTAL) {
+ setRcsJson["dimmingSetting"] = value;
+ href = this.href.h;
+ } else {
+ scplugin.log.debug(className, arguments.callee.name, "Servo Motor invalid type!");
+ }
+
+ ocfDevice.setRemoteRepresentation(href, setRcsJson, this.onRepresentCallback);
+ },
+
+ 'moveDown' : function() {
+ var nextVal = this.valueV + SERVO_STEP.VERTICAL;
+ if (nextVal >= SERVO_RANGE.VERTICAL.MAX)
+ nextVal = SERVO_RANGE.VERTICAL.MAX;
+
+ this.move(CONTROL_TYPE_VERTICAL, nextVal);
+ },
+
+ 'moveUp' : function() {
+ var nextVal = this.valueV - SERVO_STEP.VERTICAL;
+ if (nextVal <= SERVO_RANGE.VERTICAL.MIN)
+ nextVal = SERVO_RANGE.VERTICAL.MIN;
+
+ this.move(CONTROL_TYPE_VERTICAL, nextVal);
+ },
+ 'moveLeft' : function() {
+ var nextVal = this.valueH + SERVO_STEP.HORIZONTAL;
+ if (nextVal >= SERVO_RANGE.HORIZONTAL.MAX)
+ nextVal = SERVO_RANGE.HORIZONTAL.MAX;
+
+ this.move(CONTROL_TYPE_HORIZONTAL, nextVal);
+ },
+ 'moveRight' : function() {
+ var nextVal = this.valueH - SERVO_STEP.HORIZONTAL;
+ if (nextVal <= SERVO_RANGE.HORIZONTAL.MIN)
+ nextVal = SERVO_RANGE.HORIZONTAL.MIN;
+
+ this.move(CONTROL_TYPE_HORIZONTAL, nextVal);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd 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.
+ */
+
+var ocfDevice;
+var capabilities = [capabilityModeSwitch, capabilityMotionSensor, capabilityServoMotor];
+var className = "iot2018";
+
+window.onload = function () {
+ console.log("version : 0.0.1");
+ registerTouchEvents();
+ init();
+};
+
+function init() {
+ console.log("-----------init-----------");
+ scplugin.manager.getOCFDevices(getOCFDeviceCB);
+}
+
+function getOCFDeviceCB(devices) {
+ console.log("getOCFDeviceCB : " + devices.length);
+
+ for (var i in devices) {
+ console.log("deviceHandle: " + devices[i].deviceHandle);
+ console.log("deviceName: " + devices[i].deviceName);
+ console.log("deviceType: " + devices[i].deviceType);
+ console.log("metadata: " + devices[i].metadata);
+ }
+
+ setMainDevice(devices[0]);
+ ocfDevice.subscribe(onRepresentCallback);
+
+ for (var i = 0; i < capabilities.length; i++) {
+ capabilities[i].update();
+ }
+}
+
+function onRepresentCallback(result, deviceHandle, uri, rcsJsonString) {
+ for (var i = 0; i < capabilities.length; i++) {
+ var hrefObj = capabilities[i].href;
+
+ for (var item in hrefObj) {
+ if (hrefObj[item] == uri)
+ capabilities[i].onRepresentCallback(result, deviceHandle, uri, rcsJsonString);
+ }
+ }
+}
+
+function registerTouchEvents() {
+ var elements = document.getElementsByClassName("icon-move");
+ // up-left-right-down
+
+ // Move Up
+ elements[0].addEventListener("touchstart", function() {
+ if (!capabilityModeSwitch.isControllable()){
+ return;
+ }
+ document.getElementById("camera_controller").className = "shadow-up";
+ }, false);
+
+ // Move Left
+ elements[1].addEventListener("touchstart", function() {
+ if (!capabilityModeSwitch.isControllable()){
+ return;
+ }
+ document.getElementById("camera_controller").className = "shadow-left";
+ }, false);
+
+ // Move Right
+ elements[2].addEventListener("touchstart", function() {
+ if (!capabilityModeSwitch.isControllable()){
+ return;
+ }
+ document.getElementById("camera_controller").className = "shadow-right";
+ }, false);
+
+ // Move Down
+ elements[3].addEventListener("touchstart", function() {
+ if (!capabilityModeSwitch.isControllable()){
+ return;
+ }
+ document.getElementById("camera_controller").className = "shadow-down";
+ }, false);
+
+ for (var i = 0; i < elements.length; i++){
+ elements[i].addEventListener("touchend", function() {
+ document.getElementById("camera_controller").className = "";
+ }, false);
+ }
+}
+
+function setMainDevice(device) {
+ scplugin.log.debug(className, arguments.callee.name, "set ocf device : " + device.deviceName);
+ ocfDevice = device;
+}
+
+function backAction() {
+ scplugin.manager.close();
+}
+
+function onModeBtnClicked() {
+ capabilityModeSwitch.modeToggle();
+}
+
+function onMoveUpBtnClicked() {
+ if (!capabilityModeSwitch.isControllable()){
+ return;
+ }
+ capabilityServoMotor.moveUp();
+}
+
+function onMoveDownBtnClicked() {
+ if (!capabilityModeSwitch.isControllable()){
+ return;
+ }
+ capabilityServoMotor.moveDown();
+}
+
+function onMoveLeftBtnClicked() {
+ if (!capabilityModeSwitch.isControllable()){
+ return;
+ }
+ capabilityServoMotor.moveLeft();
+}
+
+function onMoveRightBtnClicked() {
+ if (!capabilityModeSwitch.isControllable()){
+ return;
+ }
+ capabilityServoMotor.moveRight();
+}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" ?>
+ <manifest xmlns="http://samsung.com/ns/plugin"
+ manifestVersionCode="0"
+ package="iot2018"
+ versionCode="1"
+ versionName="0.0.1"
+ minPluginSdkVersion="1.0.0">
+
+ <plugin label="default.plugin" icon="icon.png" >
+ <device type="none"
+ subType="none"
+ manufacturer="default.manufacturer"
+ manufacturerID="default.manufacturer.id" />
+ </plugin>
+ <privilegeLevel level="public"/>
+</manifest>
--- /dev/null
+{
+ "modelCd": "YOUR_DEVICE_NAME",
+ "easysetupId": "001"
+}
\ No newline at end of file
--- /dev/null
+ /*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ *
+ * 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 <glib.h>
+#include <Ecore.h>
+#include <tizen.h>
+#include <service_app.h>
+#include <camera.h>
+#include <mv_common.h>
+#include <pthread.h>
+#include "controller.h"
+#include "controller_mv.h"
+#include "controller_image.h"
+#include "log.h"
+#include "resource_camera.h"
+#include "switch.h"
+#include "servo-h.h"
+#include "servo-v.h"
+#include "servo-type.h"
+#include "motion.h"
+#include "st_thing_master.h"
+#include "st_thing_resource.h"
+
+#define CAMERA_MOVE_INTERVAL_MS 450
+#define THRESHOLD_EVENT_COUNT 2
+#define VALID_EVENT_INTERVAL_MS 200
+
+#define IMAGE_FILE_PREFIX "CAM_"
+#define EVENT_INTERVAL_SECOND 0.5f
+
+#define TEMP_IMAGE_FILENAME "/tmp/tmp.jpg"
+#define LATEST_IMAGE_FILENAME "/tmp/latest.jpg"
+
+// #define TEST_SERVO_MOTER_CAL 1
+// #define TEST_DEBUG_MODE 1
+// #define ENABLE_SMARTTHINGS
+#define APP_CALLBACK_KEY "controller"
+
+typedef struct app_data_s {
+ long long int last_moved_time;
+ long long int last_valid_event_time;
+ double current_servo_x;
+ double current_servo_y;
+ int motion_state;
+
+ int vision_result_x_sum;
+ int vision_result_y_sum;
+
+ int valid_event_count;
+
+ unsigned int latest_image_width;
+ unsigned int latest_image_height;
+ char *latest_image_info;
+ int latest_image_type; // 0: 카메라 이동 시간의 이미지, 1: 유효 이벤트 숫자 아래의 이미지, 2: 유효한 동작 이미지
+
+ unsigned char *latest_image_buffer;
+
+ Ecore_Thread *image_writter_thread;
+ pthread_mutex_t mutex;
+} app_data;
+
+static long long int __get_monotonic_ms(void)
+{
+ long long int ret_time = 0;
+ struct timespec time_s;
+
+ if (0 == clock_gettime(CLOCK_MONOTONIC, &time_s))
+ ret_time = time_s.tv_sec* 1000 + time_s.tv_nsec / 1000000;
+ else
+ _E("Failed to get time");
+
+ return ret_time;
+}
+
+static mv_colorspace_e __convert_colorspace_from_cam_to_mv(camera_pixel_format_e format)
+{
+ mv_colorspace_e colorspace = MEDIA_VISION_COLORSPACE_INVALID;
+ switch (format) {
+ case CAMERA_PIXEL_FORMAT_NV12:
+ colorspace = MEDIA_VISION_COLORSPACE_NV12;
+ break;
+ case CAMERA_PIXEL_FORMAT_NV21:
+ colorspace = MEDIA_VISION_COLORSPACE_NV21;
+ break;
+ case CAMERA_PIXEL_FORMAT_YUYV:
+ colorspace = MEDIA_VISION_COLORSPACE_YUYV;
+ break;
+ case CAMERA_PIXEL_FORMAT_UYVY:
+ colorspace = MEDIA_VISION_COLORSPACE_UYVY;
+ break;
+ case CAMERA_PIXEL_FORMAT_422P:
+ colorspace = MEDIA_VISION_COLORSPACE_422P;
+ break;
+ case CAMERA_PIXEL_FORMAT_I420:
+ colorspace = MEDIA_VISION_COLORSPACE_I420;
+ break;
+ case CAMERA_PIXEL_FORMAT_YV12:
+ colorspace = MEDIA_VISION_COLORSPACE_YV12;
+ break;
+ case CAMERA_PIXEL_FORMAT_RGB565:
+ colorspace = MEDIA_VISION_COLORSPACE_RGB565;
+ break;
+ case CAMERA_PIXEL_FORMAT_RGB888:
+ colorspace = MEDIA_VISION_COLORSPACE_RGB888;
+ break;
+ case CAMERA_PIXEL_FORMAT_RGBA:
+ colorspace = MEDIA_VISION_COLORSPACE_RGBA;
+ break;
+ case CAMERA_PIXEL_FORMAT_NV12T:
+ case CAMERA_PIXEL_FORMAT_NV16:
+ case CAMERA_PIXEL_FORMAT_ARGB:
+ case CAMERA_PIXEL_FORMAT_JPEG:
+ case CAMERA_PIXEL_FORMAT_H264:
+ case CAMERA_PIXEL_FORMAT_INVALID:
+ default :
+ colorspace = MEDIA_VISION_COLORSPACE_INVALID;
+ _E("unsupported format : %d", format);
+ break;
+ }
+
+ return colorspace;
+}
+
+static void __thread_write_image_file(void *data, Ecore_Thread *th)
+{
+ app_data *ad = (app_data *)data;
+ unsigned int width = 0;
+ unsigned int height = 0;
+ unsigned char *buffer = 0;
+ char *image_info = NULL;
+ int ret = 0;
+
+ pthread_mutex_lock(&ad->mutex);
+ width = ad->latest_image_width;
+ height = ad->latest_image_height;
+ buffer = ad->latest_image_buffer;
+ ad->latest_image_buffer = NULL;
+ if (ad->latest_image_info) {
+ image_info = ad->latest_image_info;
+ ad->latest_image_info = NULL;
+ } else {
+ image_info = strdup("00");
+ }
+ pthread_mutex_unlock(&ad->mutex);
+
+#ifdef TEST_DEBUG_MODE
+ char filename[PATH_MAX] = {'\0', };
+ static long long int captured_time = 0;
+ long long int now = __get_monotonic_ms();
+ int servo_x = 0;
+ int servo_y = 0;
+ int latest_image_type = 0;
+
+ char *data_path = NULL;
+ data_path = app_get_data_path();
+
+ pthread_mutex_lock(&ad->mutex);
+ servo_x = (int)ad->current_servo_x;
+ servo_y = (int)ad->current_servo_y;
+ latest_image_type = ad->latest_image_type;
+ pthread_mutex_unlock(&ad->mutex);
+
+ snprintf(filename, PATH_MAX, "%s%s%lld_H_%d_V_%d_%lld_%d.jpg",
+ data_path,
+ IMAGE_FILE_PREFIX,
+ __get_monotonic_ms(),
+ servo_x,
+ servo_y,
+ __get_monotonic_ms() - captured_time,
+ latest_image_type);
+
+ free(data_path);
+ data_path = NULL;
+
+ ret = controller_image_save_image_file(filename, width, height, buffer, image_info, strlen(image_info));
+ if (ret)
+ _E("failed to save image file");
+
+ captured_time = __get_monotonic_ms();
+#else
+ ret = controller_image_save_image_file(TEMP_IMAGE_FILENAME, width, height, buffer, image_info, strlen(image_info));
+ if (ret) {
+ _E("failed to save image file");
+ } else {
+ ret = rename(TEMP_IMAGE_FILENAME, LATEST_IMAGE_FILENAME);
+ if (ret != 0 )
+ _E("Rename fail");
+ }
+#endif
+ free(image_info);
+ free(buffer);
+}
+
+static void __thread_end_cb(void *data, Ecore_Thread *th)
+{
+ app_data *ad = (app_data *)data;
+
+ // _D("Normal termination for thread %p.\n", th);
+ pthread_mutex_lock(&ad->mutex);
+ ad->image_writter_thread = NULL;
+ pthread_mutex_unlock(&ad->mutex);
+}
+
+static void __thread_cancel_cb(void *data, Ecore_Thread *th)
+{
+ app_data *ad = (app_data *)data;
+ unsigned char *buffer = NULL;
+
+ _E("Thread %p got cancelled.\n", th);
+ pthread_mutex_lock(&ad->mutex);
+ buffer = ad->latest_image_buffer;
+ ad->latest_image_buffer = NULL;
+ ad->image_writter_thread = NULL;
+ pthread_mutex_unlock(&ad->mutex);
+
+ free(buffer);
+}
+
+static void __copy_image_buffer(image_buffer_data_s *image_buffer, app_data *ad)
+{
+ unsigned char *buffer = NULL;
+
+ pthread_mutex_lock(&ad->mutex);
+ ad->latest_image_height = image_buffer->image_height;
+ ad->latest_image_width = image_buffer->image_width;
+
+ buffer = ad->latest_image_buffer;
+ ad->latest_image_buffer = image_buffer->buffer;
+ pthread_mutex_unlock(&ad->mutex);
+
+ free(buffer);
+}
+
+static void __preview_image_buffer_created_cb(void *data)
+{
+ image_buffer_data_s *image_buffer = data;
+ app_data *ad = (app_data *)image_buffer->user_data;
+ mv_source_h source = NULL;
+ mv_colorspace_e image_colorspace = MEDIA_VISION_COLORSPACE_INVALID;
+ switch_state_e switch_state = SWITCH_STATE_OFF;
+ char *info = NULL;
+
+ ret_if(!image_buffer);
+ ret_if(!ad);
+
+#ifdef TEST_DEBUG_MODE
+ static long long int last_time = 0;
+ static int seq = 0;
+ long long int now = __get_monotonic_ms();
+ seq++;
+ _D("BUFFER seq[%d] interval[%lld]", seq, now - last_time);
+ last_time = now;
+#endif
+
+ image_colorspace = __convert_colorspace_from_cam_to_mv(image_buffer->format);
+ goto_if(image_colorspace == MEDIA_VISION_COLORSPACE_INVALID, FREE_ALL_BUFFER);
+
+ __copy_image_buffer(image_buffer, ad);
+
+ switch_state_get(&switch_state);
+ if (switch_state == SWITCH_STATE_OFF) { /* SWITCH_STATE_OFF means automatic mode */
+ source = controller_mv_create_source(image_buffer->buffer,
+ image_buffer->buffer_size, image_buffer->image_width,
+ image_buffer->image_height, image_colorspace);
+ }
+
+ pthread_mutex_lock(&ad->mutex);
+ info = ad->latest_image_info;
+ ad->latest_image_info = NULL;
+ pthread_mutex_unlock(&ad->mutex);
+ free(info);
+
+ if (source)
+ controller_mv_push_source(source);
+
+#ifdef TEST_DEBUG_MODE
+ _D("Vision need %lldms", __get_monotonic_ms() - now);
+#endif
+ free(image_buffer);
+
+ motion_state_set(ad->motion_state, APP_CALLBACK_KEY);
+ ad->motion_state = 0;
+
+ pthread_mutex_lock(&ad->mutex);
+ if (!ad->image_writter_thread) {
+ ad->image_writter_thread = ecore_thread_run(__thread_write_image_file, __thread_end_cb, __thread_cancel_cb, ad);
+ } else {
+ _E("Thread is running NOW");
+ }
+ pthread_mutex_unlock(&ad->mutex);
+
+ return;
+
+FREE_ALL_BUFFER:
+ free(image_buffer->buffer);
+ free(image_buffer);
+}
+
+// x, y -10 ~ 10 offset
+static void __move_camera(int x, int y, void *user_data)
+{
+ app_data *ad = (app_data *)user_data;
+ ret_if(!ad);
+
+ if (x > 10) x = 10;
+ if (x < -10) x = -10;
+ if (y > 10) y = 10;
+ if (y < -10) y = -10;
+
+ x *= -1; // 카메라는 좌우 반전!!
+ double calculated_x = ad->current_servo_x + x * SERVO_MOTOR_HORIZONTAL_STEP;
+ double calculated_y = ad->current_servo_y + y * SERVO_MOTOR_VERTICAL_STEP;
+
+ if (calculated_x > SERVO_MOTOR_HORIZONTAL_MAX)
+ calculated_x = SERVO_MOTOR_HORIZONTAL_MAX;
+
+ if (calculated_x < SERVO_MOTOR_HORIZONTAL_MIN)
+ calculated_x = SERVO_MOTOR_HORIZONTAL_MIN;
+
+ if (calculated_y > SERVO_MOTOR_VERTICAL_MAX)
+ calculated_y = SERVO_MOTOR_VERTICAL_MAX;
+
+ if (calculated_y < SERVO_MOTOR_VERTICAL_MIN)
+ calculated_y = SERVO_MOTOR_VERTICAL_MIN;
+
+ ad->current_servo_x = calculated_x;
+ ad->current_servo_y = calculated_y;
+
+ servo_h_state_set(calculated_x, APP_CALLBACK_KEY);
+ servo_v_state_set(calculated_y, APP_CALLBACK_KEY);
+
+ return;
+}
+
+static void __set_result_info(int result[], int result_count, app_data *ad, int image_result_type)
+{
+ char image_info[IMAGE_INFO_MAX + 1] = {'\0', };
+ char *current_position;
+ int current_index = 0;
+ int string_count = 0;
+ int i = 0;
+ char *latest_image_info = NULL;
+ char *info = NULL;
+
+ current_position = image_info;
+
+ current_position += snprintf(current_position, IMAGE_INFO_MAX, "%02d", image_result_type);
+ string_count += 2;
+
+ current_position += snprintf(current_position, IMAGE_INFO_MAX - string_count, "%02d", result_count);
+ string_count += 2;
+
+ for (i = 0; i < result_count; i++) {
+ current_index = i * 4;
+#ifdef TEST_DEBUG_MODE
+ _D("RESULT: [%02d] [%02d] [%02d] [%02d]", result[i], result[i + 1], result[i + 2], result[i + 3]);
+#endif
+ if (IMAGE_INFO_MAX - string_count < 0)
+ break;
+
+ current_position += snprintf(current_position, IMAGE_INFO_MAX - string_count, "%02d%02d%02d%02d"
+ , result[current_index], result[current_index + 1], result[current_index + 2], result[current_index + 3]);
+ string_count += 8;
+ }
+
+#ifdef TEST_DEBUG_MODE
+ _D("RESULT: Count [%02d] String [%s]", result_count, image_info);
+#endif
+ latest_image_info = strdup(image_info);
+ pthread_mutex_lock(&ad->mutex);
+ info = ad->latest_image_info;
+ ad->latest_image_info = latest_image_info;
+ pthread_mutex_unlock(&ad->mutex);
+ free(info);
+}
+
+static void __mv_detection_event_cb(int horizontal, int vertical, int result[], int result_count, void *user_data)
+{
+ app_data *ad = (app_data *)user_data;
+ long long int now = __get_monotonic_ms();
+
+ ad->motion_state = 1;
+
+ if (now < ad->last_moved_time + CAMERA_MOVE_INTERVAL_MS) {
+ // _D("@@@ CAMERA MOVE TIME @@@");
+ ad->valid_event_count = 0;
+ pthread_mutex_lock(&ad->mutex);
+ ad->latest_image_type = 0;
+ pthread_mutex_unlock(&ad->mutex);
+ __set_result_info(result, result_count, ad, 0);
+ return;
+ }
+
+ if (now < ad->last_valid_event_time + VALID_EVENT_INTERVAL_MS) {
+ ad->valid_event_count++;
+ } else {
+ ad->valid_event_count = 1;
+ }
+
+ ad->last_valid_event_time = now;
+
+ if (ad->valid_event_count < THRESHOLD_EVENT_COUNT) {
+ ad->vision_result_x_sum += horizontal;
+ ad->vision_result_y_sum += vertical;
+ pthread_mutex_lock(&ad->mutex);
+ ad->latest_image_type = 1;
+ pthread_mutex_unlock(&ad->mutex);
+ __set_result_info(result, result_count, ad, 1);
+ return;
+ }
+
+ ad->valid_event_count = 0;
+ ad->vision_result_x_sum += horizontal;
+ ad->vision_result_y_sum += vertical;
+
+ int x = ad->vision_result_x_sum / THRESHOLD_EVENT_COUNT;
+ int y = ad->vision_result_y_sum / THRESHOLD_EVENT_COUNT;
+
+ x = 10 * x / (IMAGE_WIDTH / 2);
+ y = 10 * y / (IMAGE_HEIGHT / 2);
+
+#ifndef TEST_SERVO_MOTER_CAL
+ __move_camera((int) x, (int) y, ad);
+#endif
+ ad->last_moved_time = now;
+
+ ad->vision_result_x_sum = 0;
+ ad->vision_result_y_sum = 0;
+ pthread_mutex_lock(&ad->mutex);
+ ad->latest_image_type = 2;
+ pthread_mutex_unlock(&ad->mutex);
+
+ __set_result_info(result, result_count, ad, 2);
+}
+
+#ifdef TEST_SERVO_MOTER_CAL
+static Eina_Bool _control_interval_event_cb(void *data)
+{
+ static int h = SERVO_MOTOR_HORIZONTAL_MIN;
+ static int v = SERVO_MOTOR_VERTICAL_MIN;
+
+ v += SERVO_MOTOR_VERTICAL_STEP;
+ if (v > SERVO_MOTOR_VERTICAL_MAX)
+ v = SERVO_MOTOR_VERTICAL_MIN;
+
+ h += SERVO_MOTOR_HORIZONTAL_STEP;
+ if (h > SERVO_MOTOR_HORIZONTAL_MAX)
+ h = SERVO_MOTOR_HORIZONTAL_MIN;
+
+ // servo_h_state_set(h, APP_CALLBACK_KEY);
+ // servo_v_state_set(v, APP_CALLBACK_KEY);
+
+ _D("SERVO V ONLY v[%d] h[%d]", v, h);
+
+ return ECORE_CALLBACK_RENEW;
+}
+#endif
+
+static void __switch_changed(switch_state_e state, void* user_data)
+{
+ app_data *ad = (app_data *)user_data;
+ _D("switch changed to - %d", state);
+ ret_if(!ad);
+
+ /* Move servo motors to initial position */
+ if (state != SWITCH_STATE_ON)
+ return;
+
+ ad->current_servo_x = SERVO_MOTOR_HORIZONTAL_CENTER;
+ ad->current_servo_y = SERVO_MOTOR_VERTICAL_CENTER;
+
+ servo_h_state_set(ad->current_servo_x, APP_CALLBACK_KEY);
+ servo_v_state_set(ad->current_servo_y, APP_CALLBACK_KEY);
+}
+
+static void __servo_v_changed(double value, void* user_data)
+{
+ app_data *ad = (app_data *)user_data;
+ ret_if(!ad);
+
+ _D("servo_v changed to - %lf", value);
+ ad->current_servo_y = value;
+}
+
+static void __servo_h_changed(double value, void* user_data)
+{
+ app_data *ad = (app_data *)user_data;
+ ret_if(!ad);
+
+ _D("servo_h changed to - %lf", value);
+ ad->current_servo_x = value;
+}
+
+static void __device_interfaces_fini(void)
+{
+ switch_finalize();
+ servo_v_finalize();
+ servo_h_finalize();
+ motion_finalize();
+}
+
+static int __device_interfaces_init(app_data *ad)
+{
+ retv_if(!ad, -1);
+
+ if (switch_initialize()) {
+ _E("failed to switch_initialize()");
+ return -1;
+ }
+
+ if (servo_v_initialize()) {
+ _E("failed to switch_initialize()");
+ goto ERROR;
+ }
+
+ if (servo_h_initialize()) {
+ _E("failed to switch_initialize()");
+ goto ERROR;
+ }
+
+ if (motion_initialize()) {
+ _E("failed to motion_initialize()");
+ goto ERROR;
+ }
+
+ switch_state_changed_cb_set(APP_CALLBACK_KEY, __switch_changed, ad);
+ servo_v_state_changed_cb_set(APP_CALLBACK_KEY, __servo_v_changed, ad);
+ servo_h_state_changed_cb_set(APP_CALLBACK_KEY, __servo_h_changed, ad);
+ // motion : only set result value, callback is not needed
+
+ return 0;
+
+ERROR :
+ __device_interfaces_fini();
+ return -1;
+}
+
+static bool service_app_create(void *data)
+{
+ app_data *ad = (app_data *)data;
+
+ controller_image_initialize();
+
+ pthread_mutex_init(&ad->mutex, NULL);
+
+ if (__device_interfaces_init(ad))
+ goto ERROR;
+
+ if (controller_mv_set_movement_detection_event_cb(__mv_detection_event_cb, data) == -1) {
+ _E("Failed to set movement detection event callback");
+ goto ERROR;
+ }
+
+ if (resource_camera_init(__preview_image_buffer_created_cb, ad) == -1) {
+ _E("Failed to init camera");
+ goto ERROR;
+ }
+
+#ifdef TEST_SERVO_MOTER_CAL
+ ecore_timer_add(EVENT_INTERVAL_SECOND, _control_interval_event_cb, NULL);
+#endif
+
+ if (resource_camera_start_preview() == -1) {
+ _E("Failed to start camera preview");
+ goto ERROR;
+ }
+
+#ifdef ENABLE_SMARTTHINGS
+ /* smartthings APIs should be called after camera start preview, they can't wait to start camera */
+ if (st_thing_master_init())
+ goto ERROR;
+
+ if (st_thing_resource_init())
+ goto ERROR;
+#endif /* ENABLE_SMARTTHINGS */
+
+ ad->current_servo_x = SERVO_MOTOR_HORIZONTAL_CENTER;
+ ad->current_servo_y = SERVO_MOTOR_VERTICAL_CENTER;
+
+ servo_h_state_set(ad->current_servo_x, APP_CALLBACK_KEY);
+ servo_v_state_set(ad->current_servo_y, APP_CALLBACK_KEY);
+
+ return true;
+
+ERROR:
+ __device_interfaces_fini();
+
+ resource_camera_close();
+ controller_mv_unset_movement_detection_event_cb();
+ controller_image_finalize();
+
+#ifdef ENABLE_SMARTTHINGS
+ st_thing_master_fini();
+ st_thing_resource_fini();
+#endif /* ENABLE_SMARTTHINGS */
+
+ pthread_mutex_destroy(&ad->mutex);
+
+ return false;
+}
+
+static void service_app_terminate(void *data)
+{
+ app_data *ad = (app_data *)data;
+ Ecore_Thread *thread_id = NULL;
+ unsigned char *buffer = NULL;
+ char *info = NULL;
+ _D("App Terminated - enter");
+
+ resource_camera_close();
+ controller_mv_unset_movement_detection_event_cb();
+
+ pthread_mutex_lock(&ad->mutex);
+ thread_id = ad->image_writter_thread;
+ ad->image_writter_thread = NULL;
+ pthread_mutex_unlock(&ad->mutex);
+
+ if (thread_id)
+ ecore_thread_wait(thread_id, 3.0); // wait for 3 second
+
+ __device_interfaces_fini();
+
+ controller_image_finalize();
+
+#ifdef ENABLE_SMARTTHINGS
+ st_thing_master_fini();
+ st_thing_resource_fini();
+#endif /* ENABLE_SMARTTHINGS */
+
+ pthread_mutex_lock(&ad->mutex);
+ buffer = ad->latest_image_buffer;
+ ad->latest_image_buffer = NULL;
+ info = ad->latest_image_info;
+ ad->latest_image_info = NULL;
+ pthread_mutex_unlock(&ad->mutex);
+ free(buffer);
+ free(info);
+
+ pthread_mutex_destroy(&ad->mutex);
+ free(ad);
+ _D("App Terminated - leave");
+}
+
+static void service_app_control(app_control_h app_control, void *data)
+{
+ /* APP_CONTROL */
+}
+
+int main(int argc, char* argv[])
+{
+ app_data *ad = NULL;
+ int ret = 0;
+ service_app_lifecycle_callback_s event_callback;
+
+ ad = calloc(1, sizeof(app_data));
+ retv_if(!ad, -1);
+
+ event_callback.create = service_app_create;
+ event_callback.terminate = service_app_terminate;
+ event_callback.app_control = service_app_control;
+
+ ret = service_app_main(argc, argv, &event_callback, ad);
+
+ return ret;
+}
--- /dev/null
+ /*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ *
+ * 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 <glib.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <tizen.h>
+#include <image_util.h>
+#include "log.h"
+#include "exif.h"
+
+static image_util_encode_h encode_h = NULL;
+static image_util_decode_h decode_h = NULL;
+
+#define IMAGE_COLORSPACE IMAGE_UTIL_COLORSPACE_I420
+
+void controller_image_initialize(void)
+{
+ int error_code = image_util_encode_create(IMAGE_UTIL_JPEG, &encode_h);
+ if (error_code != IMAGE_UTIL_ERROR_NONE) {
+ _E("image_util_encode_create [%s]", get_error_message(error_code));
+ }
+
+ error_code = image_util_decode_create(&decode_h);
+ if (error_code != IMAGE_UTIL_ERROR_NONE) {
+ _E("image_util_decode_create [%s]", get_error_message(error_code));
+ }
+}
+
+void controller_image_finalize(void)
+{
+ int error_code = image_util_encode_destroy(encode_h);
+ if (error_code != IMAGE_UTIL_ERROR_NONE) {
+ _E("image_util_encode_destroy [%s]", get_error_message(error_code));
+ }
+
+ error_code = image_util_decode_destroy(decode_h);
+ if (error_code != IMAGE_UTIL_ERROR_NONE) {
+ _E("image_util_decode_destroy [%s]", get_error_message(error_code));
+ }
+}
+
+int controller_image_save_image_file(const char *path,
+ unsigned int width, unsigned int height, const unsigned char *buffer,
+ const char *comment, unsigned int comment_len)
+{
+ unsigned char *encoded = NULL;
+ unsigned long long size = 0;
+
+ int error_code = image_util_encode_set_resolution(encode_h, width, height);
+ if (error_code != IMAGE_UTIL_ERROR_NONE) {
+ _E("image_util_encode_set_resolution [%s]", get_error_message(error_code));
+ return -1;
+ }
+
+ error_code = image_util_encode_set_colorspace(encode_h, IMAGE_COLORSPACE);
+ if (error_code != IMAGE_UTIL_ERROR_NONE) {
+ _E("image_util_encode_set_colorspace [%s]", get_error_message(error_code));
+ return -1;
+ }
+
+ error_code = image_util_encode_set_quality(encode_h, 90);
+ if (error_code != IMAGE_UTIL_ERROR_NONE) {
+ _E("image_util_encode_set_quality [%s]", get_error_message(error_code));
+ return -1;
+ }
+
+ error_code = image_util_encode_set_input_buffer(encode_h, buffer);
+ if (error_code != IMAGE_UTIL_ERROR_NONE) {
+ _E("image_util_encode_set_input_buffer [%s]", get_error_message(error_code));
+ return -1;
+ }
+
+ error_code = image_util_encode_set_output_buffer(encode_h, &encoded);
+ if (error_code != IMAGE_UTIL_ERROR_NONE) {
+ _E("image_util_encode_set_output_buffer [%s]", get_error_message(error_code));
+ return -1;
+ }
+
+ error_code = image_util_encode_run(encode_h, &size);
+ if (error_code != IMAGE_UTIL_ERROR_NONE) {
+ _E("image_util_encode_run [%s]", get_error_message(error_code));
+ return -1;
+ }
+
+ error_code = exif_write_jpg_file_with_comment(path,
+ encoded, (unsigned int)size, width, height, comment, comment_len);
+
+ free(encoded);
+
+ return error_code;
+}
+
+int controller_image_read_image_file(const char *path,
+ unsigned long *width, unsigned long *height, unsigned char *buffer, unsigned long long *size)
+{
+ int error_code = image_util_decode_set_input_path(decode_h, path);
+ if (error_code != IMAGE_UTIL_ERROR_NONE) {
+ _E("image_util_decode_set_input_path [%s] [%s]", path, get_error_message(error_code));
+ return -1;
+ }
+
+ error_code = image_util_decode_set_output_buffer(decode_h, &buffer);
+ if (error_code != IMAGE_UTIL_ERROR_NONE) {
+ _E("image_util_decode_set_output_buffer [%s]", get_error_message(error_code));
+ return -1;
+ }
+
+ error_code = image_util_decode_set_colorspace(decode_h, IMAGE_UTIL_COLORSPACE_RGBA8888);
+ if (error_code != IMAGE_UTIL_ERROR_NONE) {
+ _E("image_util_decode_set_colorspace [%s]", get_error_message(error_code));
+ return -1;
+ }
+
+ error_code = image_util_decode_set_jpeg_downscale(decode_h, IMAGE_UTIL_DOWNSCALE_1_1);
+ if (error_code != IMAGE_UTIL_ERROR_NONE) {
+ _E("image_util_decode_set_jpeg_downscale [%s]", get_error_message(error_code));
+ return -1;
+ }
+
+ error_code = image_util_decode_run(decode_h, width, height, size);
+ if (error_code != IMAGE_UTIL_ERROR_NONE) {
+ _E("image_util_decode_run [%s]", get_error_message(error_code));
+ return -1;
+ }
+
+ return error_code;
+}
--- /dev/null
+ /*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ *
+ * 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 <glib.h>
+#include <stdlib.h>
+#include <mv_common.h>
+#include <mv_surveillance.h>
+#include "controller.h"
+#include "controller_mv.h"
+#include "log.h"
+
+#define VIDEO_STREAM_ID 0
+#define THRESHOLD_SIZE_REGION 100
+
+struct __mv_data {
+ mv_surveillance_event_trigger_h mv_trigger_handle;
+ movement_detected_cb movement_detected_cb;
+ void *movement_detected_cb_data;
+};
+
+static struct __mv_data *mv_data = NULL;
+
+static const char *__mv_err_to_str(mv_error_e err)
+{
+ const char *err_str;
+ switch (err) {
+ case MEDIA_VISION_ERROR_NONE:
+ err_str = "MEDIA_VISION_ERROR_NONE";
+ break;
+ case MEDIA_VISION_ERROR_NOT_SUPPORTED:
+ err_str = "MEDIA_VISION_ERROR_NOT_SUPPORTED";
+ break;
+ case MEDIA_VISION_ERROR_MSG_TOO_LONG:
+ err_str = "MEDIA_VISION_ERROR_MSG_TOO_LONG";
+ break;
+ case MEDIA_VISION_ERROR_NO_DATA:
+ err_str = "MEDIA_VISION_ERROR_NO_DATA";
+ break;
+ case MEDIA_VISION_ERROR_KEY_NOT_AVAILABLE:
+ err_str = "MEDIA_VISION_ERROR_KEY_NOT_AVAILABLE";
+ break;
+ case MEDIA_VISION_ERROR_OUT_OF_MEMORY:
+ err_str = "MEDIA_VISION_ERROR_OUT_OF_MEMORY";
+ break;
+ case MEDIA_VISION_ERROR_INVALID_PARAMETER:
+ err_str = "MEDIA_VISION_ERROR_INVALID_PARAMETER";
+ break;
+ case MEDIA_VISION_ERROR_INVALID_OPERATION:
+ err_str = "MEDIA_VISION_ERROR_INVALID_OPERATION";
+ break;
+ case MEDIA_VISION_ERROR_PERMISSION_DENIED:
+ err_str = "MEDIA_VISION_ERROR_PERMISSION_DENIED";
+ break;
+ case MEDIA_VISION_ERROR_NOT_SUPPORTED_FORMAT:
+ err_str = "MEDIA_VISION_ERROR_NOT_SUPPORTED_FORMAT";
+ break;
+ case MEDIA_VISION_ERROR_INTERNAL:
+ err_str = "MEDIA_VISION_ERROR_INTERNAL";
+ break;
+ case MEDIA_VISION_ERROR_INVALID_DATA:
+ err_str = "MEDIA_VISION_ERROR_INVALID_DATA";
+ break;
+ case MEDIA_VISION_ERROR_INVALID_PATH:
+ err_str = "MEDIA_VISION_ERROR_INVALID_PATH";
+ break;
+ default:
+ err_str = "Unknown Error";
+ break;
+ }
+
+ return err_str;
+}
+
+static void __movement_detected_event_cb(mv_surveillance_event_trigger_h trigger, mv_source_h source, int video_stream_id, mv_surveillance_result_h event_result, void *data)
+{
+ int ret = 0;
+ int horizontal = 0;
+ int vertical = 0;
+ int result[MV_RESULT_LENGTH_MAX] = {0, };
+ int result_count = 0;
+ int result_index = 0;
+ int valid_area_sum = 0;
+ int i;
+ size_t move_regions_num = 0;
+ mv_rectangle_s *regions = NULL;
+
+ ret_if(!trigger);
+ ret_if(!event_result);
+ ret_if(!mv_data);
+
+ ret = mv_surveillance_get_result_value(event_result, MV_SURVEILLANCE_MOVEMENT_NUMBER_OF_REGIONS, &move_regions_num);
+ retm_if(ret, "failed to mv_surveillance_get_result_value for %s - [%s]", MV_SURVEILLANCE_MOVEMENT_NUMBER_OF_REGIONS, __mv_err_to_str(ret));
+
+ regions = malloc(sizeof(mv_rectangle_s) * move_regions_num);
+ ret = mv_surveillance_get_result_value(event_result, MV_SURVEILLANCE_MOVEMENT_REGIONS, regions);
+ retm_if(ret, "failed to mv_surveillance_get_result_value for %s - [%s]", MV_SURVEILLANCE_MOVEMENT_REGIONS, __mv_err_to_str(ret));
+
+ for (i = 0; i < move_regions_num; i++) {
+ // _D("region[%u] - position[%d x %d], witdh[%d], height[%d]", i, regions[i].point.x, regions[i].point.y, regions[i].width, regions[i].height);
+ // _D("region[%u] - area[%d]", i, regions[i].width * regions[i].height);
+
+ if (regions[i].width * regions[i].height < THRESHOLD_SIZE_REGION || result_count >= MV_RESULT_COUNT_MAX)
+ continue;
+
+ result[result_index] = regions[i].point.x * 99 / IMAGE_WIDTH;
+ result[result_index + 1] = regions[i].point.y * 99 / IMAGE_HEIGHT;
+ result[result_index + 2] = regions[i].width * 99 / IMAGE_WIDTH;
+ result[result_index + 3] = regions[i].height * 99 / IMAGE_HEIGHT;
+
+ result_count++;
+ result_index = result_count * 4;
+
+ valid_area_sum += regions[i].width * regions[i].height;
+ }
+
+ for (i = 0; i < move_regions_num; i++) {
+ if (regions[i].width * regions[i].height < THRESHOLD_SIZE_REGION)
+ continue;
+
+ //offset 은 움직임의 중심 좌표가 화면의 중심으로 부터 얼마나 벗어났는지의 값으로 -160 ~ 160, -120 ~ 120 의 값을 갖는다.
+ int x_offset = (regions[i].point.x + regions[i].width / 2) - (IMAGE_WIDTH / 2);
+ int y_offset = (regions[i].point.y + regions[i].height / 2) - (IMAGE_HEIGHT / 2);
+ int area = regions[i].width * regions[i].height;
+
+ // offset 값에 움직임 크기의 상대값(비율)을 곱한 다음, 모두 더해서 최종 offset 값을 구한다.
+ // 최종값의 범위는 offset 값의 범위와 같아야 한다.
+ horizontal += (int) x_offset * area / valid_area_sum;
+ vertical += (int) y_offset * area / valid_area_sum;
+ }
+ free(regions);
+
+ mv_data->movement_detected_cb(horizontal, vertical, result, result_count, mv_data->movement_detected_cb_data);
+}
+
+void controller_mv_push_source(mv_source_h source)
+{
+ int ret = 0;
+ ret_if(!source);
+
+ ret = mv_surveillance_push_source(source, VIDEO_STREAM_ID);
+ if (ret)
+ _E("failed to mv_surveillance_push_source() - [%s]", __mv_err_to_str(ret));
+
+ mv_destroy_source(source);
+}
+
+mv_source_h controller_mv_create_source(
+ unsigned char *buffer, unsigned int size,
+ unsigned int width, unsigned int height, mv_colorspace_e colorspace)
+{
+ mv_source_h source = NULL;
+ int ret = 0;
+
+ retv_if(!buffer, NULL);
+
+ ret = mv_create_source(&source);
+ retvm_if(ret, NULL, "failed to mv_create_source - [%s]", __mv_err_to_str(ret));
+
+ ret = mv_source_fill_by_buffer(source, buffer, size, width, height, colorspace);
+ if (ret) {
+ _E("failed to fill source - %d", ret);
+
+ if (source)
+ mv_destroy_source(source);
+
+ return NULL;
+ }
+
+ return source;
+}
+
+int controller_mv_set_movement_detection_event_cb(movement_detected_cb movement_detected_cb, void *user_data)
+{
+ int ret = 0;
+ mv_engine_config_h engine_cfg = NULL;
+
+ if (movement_detected_cb == NULL)
+ return -1;
+
+ if (mv_data != NULL) {
+ mv_data->movement_detected_cb = movement_detected_cb;
+ mv_data->movement_detected_cb_data = user_data;
+ return 0;
+ }
+
+ mv_data = malloc(sizeof(struct __mv_data));
+ if (mv_data == NULL) {
+ _E("Failed to allocate media vision data");
+ return -1;
+ }
+ memset(mv_data, 0, sizeof(struct __mv_data));
+
+ ret = mv_create_engine_config(&engine_cfg);
+ if (ret) {
+ _E("failed to subsmv_create_engine_configs() - %s", __mv_err_to_str(ret));
+ goto ERROR;
+ }
+
+ mv_engine_config_set_int_attribute(engine_cfg, MV_SURVEILLANCE_MOVEMENT_DETECTION_THRESHOLD, 50); /* 10 is default value [0 ~ 255] */
+
+ ret = mv_surveillance_event_trigger_create(MV_SURVEILLANCE_EVENT_TYPE_MOVEMENT_DETECTED, &mv_data->mv_trigger_handle);
+ if (ret) {
+ _E("failed to mv_surveillance_event_trigger_create - [%s]", __mv_err_to_str(ret));
+ goto ERROR;
+ }
+
+ ret = mv_surveillance_subscribe_event_trigger(mv_data->mv_trigger_handle, VIDEO_STREAM_ID, engine_cfg, __movement_detected_event_cb, mv_data);
+
+ if (ret) {
+ _E("failed to subscribe %s - %s", MV_SURVEILLANCE_EVENT_TYPE_MOVEMENT_DETECTED, __mv_err_to_str(ret));
+ goto ERROR;
+ }
+
+ if (engine_cfg)
+ mv_destroy_engine_config(engine_cfg);
+
+ mv_data->movement_detected_cb = movement_detected_cb;
+ mv_data->movement_detected_cb_data = user_data;
+
+ return 0;
+
+ERROR:
+ if (engine_cfg)
+ mv_destroy_engine_config(engine_cfg);
+
+ if (mv_data->mv_trigger_handle)
+ mv_surveillance_event_trigger_destroy(mv_data->mv_trigger_handle);
+
+ free(mv_data);
+ mv_data = NULL;
+
+ return -1;
+}
+
+void controller_mv_unset_movement_detection_event_cb(void)
+{
+ if (mv_data == NULL)
+ return;
+
+ if (mv_data->mv_trigger_handle)
+ mv_surveillance_event_trigger_destroy(mv_data->mv_trigger_handle);
+
+ free(mv_data);
+ mv_data = NULL;
+}
--- /dev/null
+ /*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ *
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <libexif/exif-loader.h>
+#include <libexif/exif-utils.h>
+#include <libexif/exif-data.h>
+#include "log.h"
+
+#define ASCII_COMMENT_HEADER "ASCII\0\0\0"
+// #define CHECK_EXIF_BEFOR_CREATE
+
+static int check_exif_from_data(const unsigned char *img, unsigned int size)
+{
+#ifdef CHECK_EXIF_BEFOR_CREATE
+ ExifLoader *loader = NULL;
+ unsigned char ret = 0;
+ const unsigned char *buf = NULL;
+ unsigned int b_size = 0;
+
+ retv_if(!img, -1);
+ retv_if(size == 0, -1);
+
+ loader = exif_loader_new();
+ retv_if(!loader, -1);
+
+ ret = exif_loader_write(loader, img, size);
+ if (ret) {
+ _E("failed to loader write");
+ exif_loader_unref(loader);
+ return -1;
+ }
+
+ exif_loader_get_buf(loader, &buf, &b_size);
+ if (buf) {
+ _E("image has already exif data [%u]", b_size);
+ exif_loader_unref(loader);
+ return -1;
+ }
+
+ exif_loader_unref(loader);
+#endif /* CHECK_EXIF_BEFOR_CREATE */
+
+ return 0;
+}
+
+static ExifEntry *
+add_tag_by_init(ExifData *exif, ExifIfd ifd, ExifTag tag)
+{
+ ExifEntry *entry = NULL;
+
+ retv_if(!exif, NULL);
+
+ entry = exif_content_get_entry(exif->ifd[ifd], tag);
+ if (!entry) {
+ entry = exif_entry_new();
+ retv_if(!entry, NULL);
+
+ exif_entry_initialize(entry, tag);
+
+ entry->tag = tag;
+ exif_content_add_entry(exif->ifd[ifd], entry);
+
+ exif_entry_unref(entry);
+ }
+ return entry;
+}
+
+static ExifEntry *
+add_tag_by_malloc(ExifData *exif, ExifIfd ifd, ExifTag tag, unsigned int size)
+{
+ ExifEntry *entry = NULL;
+ void *buffer = NULL;
+ ExifMem *mem = NULL;
+
+ retv_if(!exif, NULL);
+ retv_if(size == 0, NULL);
+
+ mem = exif_mem_new_default();
+ retv_if(!mem, NULL);
+
+ entry = exif_entry_new_mem(mem);
+ if (!entry) {
+ _E("failed to exif_entry_new_mem()");
+ exif_mem_unref(mem);
+ return NULL;
+ }
+
+ buffer = exif_mem_alloc(mem, size);
+ if (!buffer) {
+ _E("failed to exif_mem_alloc()");
+ exif_mem_unref(mem);
+ exif_entry_unref(entry);
+ return NULL;
+ }
+
+ entry->data = buffer;
+ entry->size = size;
+ entry->tag = tag;
+ entry->components = size;
+ entry->format = EXIF_FORMAT_UNDEFINED;
+ exif_content_add_entry (exif->ifd[ifd], entry);
+
+ exif_mem_unref(mem);
+ exif_entry_unref(entry);
+
+ return entry;
+}
+
+static ExifEntry *
+add_tag_user_comment(ExifData *exif, const char *comment, unsigned int length)
+{
+ ExifEntry *entry = NULL;
+ size_t header_size = 0;
+
+ retv_if(!exif, NULL);
+ retv_if(!comment, NULL);
+ retv_if(length == 0, NULL);
+
+ header_size = sizeof(ASCII_COMMENT_HEADER) -1;
+
+ entry = add_tag_by_malloc(exif, EXIF_IFD_EXIF, EXIF_TAG_USER_COMMENT,
+ header_size + length);
+
+ retv_if(!entry, NULL);
+
+ memcpy(entry->data, ASCII_COMMENT_HEADER, header_size);
+ memcpy(entry->data + header_size, comment, length);
+
+ return entry;
+}
+
+static int
+create_exif_data(const unsigned char *jpg_data, unsigned int jpg_size,
+ unsigned int jpg_width, unsigned int jpg_height,
+ const char *user_comment, unsigned int comment_len,
+ unsigned char **exif_data, unsigned int *exif_size)
+{
+
+ unsigned char *data;
+ unsigned int data_len;
+ ExifEntry *ee = NULL;
+ ExifData *exif = NULL;
+
+ retv_if(!jpg_data, -1);
+ retv_if(!exif_data, -1);
+ retv_if(!exif_size, -1);
+
+ if (check_exif_from_data(jpg_data, jpg_size))
+ return -1;
+
+ exif = exif_data_new();
+ retv_if(!exif, -1);
+
+ exif_data_set_option(exif, EXIF_DATA_OPTION_FOLLOW_SPECIFICATION);
+ exif_data_set_data_type(exif, EXIF_DATA_TYPE_COMPRESSED);
+ exif_data_set_byte_order(exif, EXIF_BYTE_ORDER_INTEL);
+
+ exif_data_fix(exif);
+
+ ee = add_tag_by_init(exif, EXIF_IFD_EXIF, EXIF_TAG_PIXEL_X_DIMENSION);
+ exif_set_long(ee->data, EXIF_BYTE_ORDER_INTEL, jpg_width);
+
+ ee = add_tag_by_init(exif, EXIF_IFD_EXIF, EXIF_TAG_PIXEL_Y_DIMENSION);
+ exif_set_long(ee->data, EXIF_BYTE_ORDER_INTEL, jpg_height);
+
+ ee = add_tag_user_comment(exif, user_comment, comment_len);
+
+ exif_data_save_data(exif, &data, &data_len);
+ if (!data) {
+ _E("failed to get exif data");
+ exif_data_unref(exif);
+ return -1;
+ }
+ exif_data_unref(exif);
+
+ *exif_data = data;
+ *exif_size = data_len;
+
+ return 0;
+}
+
+static int
+save_jpeg_file(const char *output_file,
+ const unsigned char *jpg_data, unsigned int jpg_size)
+{
+ FILE *fp = NULL;
+ retv_if(!output_file, -1);
+ retv_if(!jpg_data, -1);
+ retv_if(jpg_size <= 2, -1);
+
+ fp = fopen(output_file, "wb");
+ retv_if(!fp, -1);
+
+ if (1 != fwrite(jpg_data, jpg_size, 1, fp)) {
+ _E("failed to write jpg data");
+ fclose(fp);
+ return -1;
+ }
+
+ fflush(fp);
+ fclose(fp);
+
+ _D("file saved [%s]", output_file);
+
+ return 0;
+}
+
+static int
+save_jpeg_file_with_exif(const char *output_file,
+ const unsigned char *jpg_data, unsigned int jpg_size,
+ unsigned char *exif_data, unsigned int exif_size)
+{
+ FILE *fp = NULL;
+ const unsigned char exif_header[] = { 0xff, 0xd8, 0xff, 0xe1 }; // FFD8 -SOI Maker, FFE1 - APP1 Maker
+ const unsigned short exif_header_length = 4;
+ const unsigned short jpg_offset = 2; // SOI maker offset
+ unsigned short exif_length = 0;
+
+ ((unsigned char *)&exif_length)[0] = (exif_size + 2) >> 8;
+ ((unsigned char *)&exif_length)[1] = (exif_size + 2) & 0x00ff;
+
+ retv_if(!output_file, -1);
+ retv_if(!jpg_data, -1);
+ retv_if(!exif_data, -1);
+ retv_if(jpg_size <= 2, -1);
+ retv_if(exif_size == 0, -1);
+
+ fp = fopen(output_file, "wb");
+ retv_if(!fp, -1);
+
+ if (1 != fwrite(exif_header, exif_header_length, 1, fp)) {
+ _E("failed to write exif header");
+ goto ERROR;
+ }
+
+ if (1 != fwrite(&exif_length, sizeof(exif_length), 1, fp)) {
+ _E("failed to write exif legth");
+ goto ERROR;
+ }
+
+ if (1 != fwrite(exif_data, exif_size, 1, fp)) {
+ _E("failed to write exif");
+ goto ERROR;
+ }
+
+ if (1 != fwrite(jpg_data + jpg_offset, jpg_size - jpg_offset, 1, fp)) {
+ _E("failed to write jpg data");
+ goto ERROR;
+ }
+
+ fflush(fp);
+ fclose(fp);
+
+ return 0;
+ERROR:
+ fclose(fp);
+ unlink(output_file);
+ _E(" failed to save file - [%s]", output_file);
+ return -1;
+}
+
+int exif_write_jpg_file_with_comment(const char *output_file,
+ const unsigned char *jpg_data, unsigned int jpg_size,
+ unsigned int jpg_width, unsigned int jpg_height,
+ const char *comment, unsigned int comment_len)
+{
+ int ret = 0;
+ unsigned char *exif_data = NULL;
+ unsigned int exif_size = 0;
+
+ if (!comment || (comment_len == 0)) {
+ _W("There is no comment");
+ return save_jpeg_file(output_file, jpg_data, jpg_size);
+ }
+
+ ret = create_exif_data(jpg_data, jpg_size, jpg_width, jpg_height,
+ comment, comment_len, &exif_data, &exif_size);
+ if (ret) {
+ _E("failed to create_exif_data(), save jpg data only");
+ return save_jpeg_file(output_file, jpg_data, jpg_size);
+ }
+
+ ret = save_jpeg_file_with_exif(
+ output_file, jpg_data, jpg_size, exif_data, exif_size);
+
+ free(exif_data);
+ return ret;
+}
--- /dev/null
+ /*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ *
+ * 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 <stdlib.h>
+#include <pthread.h>
+#include <glib.h>
+#include "log.h"
+#include "motion.h"
+
+#define IDLE_PRIORITY (G_PRIORITY_HIGH_IDLE + 30)
+
+struct motion_data_s {
+ int state;
+ GHashTable *callback_hash;
+};
+
+struct motion_callback_s {
+ motion_state_changed_cb callback;
+ void *cb_data;
+};
+
+struct motion_pass_data_s {
+ char *pass_key;
+ int state;
+};
+
+static struct motion_data_s *g_motion;
+static pthread_mutex_t g_motion_mutex;
+
+static int __free_motion_handle(struct motion_data_s *handle)
+{
+ if (handle->callback_hash) {
+ g_hash_table_destroy(handle->callback_hash);
+ g_hash_table_unref(handle->callback_hash);
+ }
+
+ free(handle);
+ return 0;
+}
+
+int motion_initialize(void)
+{
+ if (g_motion) {
+ _D("The motion is already initialized!");
+ return 0;
+ }
+
+ g_motion = malloc(sizeof(struct motion_data_s));
+ retv_if(!g_motion, -1);
+
+ g_motion->callback_hash =
+ g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
+
+ pthread_mutex_init(&g_motion_mutex, NULL);
+ g_motion->state = 0;
+
+ /* TODO : initialize real motion detector here */
+
+ return 0;
+}
+
+int motion_finalize(void)
+{
+ if (g_motion) {
+ pthread_mutex_destroy(&g_motion_mutex);
+ __free_motion_handle(g_motion);
+ g_motion = NULL;
+ }
+
+ return 0;
+}
+
+static void __cb_item_foreach(gpointer key, gpointer value, gpointer user_data)
+{
+ char *item_name = key;
+ struct motion_callback_s *cb_item = value;
+ struct motion_pass_data_s *pass_item = user_data;
+
+ ret_if(!item_name);
+ ret_if(!cb_item);
+ ret_if(!pass_item);
+
+
+ if (pass_item->pass_key &&
+ (0 == g_strcmp0(item_name, pass_item->pass_key))) {
+ // _D("pass item - %s", item_name);
+ return;
+ }
+
+ _D("callback called for [%s]", item_name);
+ cb_item->callback(pass_item->state, cb_item->cb_data);
+}
+
+static gboolean __call_cb_idle(gpointer data)
+{
+ struct motion_pass_data_s *pass_item = data;
+
+ g_hash_table_foreach(g_motion->callback_hash, __cb_item_foreach, pass_item);
+ g_free(pass_item->pass_key);
+ g_free(pass_item);
+
+ return G_SOURCE_REMOVE;
+}
+
+int motion_state_set(int state, const char *pass_key)
+{
+ int old_state = 0;
+ retv_if(!g_motion, -1);
+
+ // _D("set state : %d", state);
+
+ pthread_mutex_lock(&g_motion_mutex);
+ old_state = g_motion->state;
+ pthread_mutex_unlock(&g_motion_mutex);
+
+ if (old_state != state) {
+ /* TODO : handle real motion detector here */
+ pthread_mutex_lock(&g_motion_mutex);
+ g_motion->state = state;
+ pthread_mutex_unlock(&g_motion_mutex);
+
+ if (g_hash_table_size(g_motion->callback_hash) > 0) {
+ struct motion_pass_data_s *pass_item = NULL;
+
+ pass_item = g_new(struct motion_pass_data_s, 1);
+ pass_item->pass_key = g_strdup(pass_key);
+ pass_item->state = state;
+ g_idle_add_full(IDLE_PRIORITY,
+ __call_cb_idle, pass_item, NULL);
+ }
+ }
+ return 0;
+}
+
+int motion_state_get(int *state)
+{
+ retv_if(!g_motion, -1);
+ retv_if(!state, -1);
+
+ pthread_mutex_lock(&g_motion_mutex);
+ *state = g_motion->state;
+ pthread_mutex_unlock(&g_motion_mutex);
+
+ // _D("get state : %d", *state);
+
+ return 0;
+}
+
+int motion_state_changed_cb_set(
+ const char *callback_key, motion_state_changed_cb callback, void *cb_data)
+{
+ retv_if(!g_motion, -1);
+ retv_if(!g_motion->callback_hash, -1);
+ retv_if(!callback_key, -1);
+
+ if (callback) {
+ struct motion_callback_s *cb_item = NULL;
+ cb_item = g_try_new(struct motion_callback_s, 1);
+ retv_if(!cb_item, -1);
+
+ cb_item->callback = callback;
+ cb_item->cb_data = cb_data;
+
+ g_hash_table_insert(g_motion->callback_hash,
+ g_strdup(callback_key), cb_item);
+ } else {
+ g_hash_table_remove(g_motion->callback_hash, callback_key);
+ }
+
+ return 0;
+}
--- /dev/null
+ /*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ *
+ * 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 <stdlib.h>
+#include <Ecore.h>
+#include <camera.h>
+#ifdef DEBUG_THREAD
+#include <pthread.h>
+#endif
+
+#include "log.h"
+#include "controller.h"
+#include "resource_camera.h"
+
+struct __camera_data {
+ camera_h cam_handle;
+
+ void *captured_file;
+ unsigned int image_size;
+
+ preview_image_buffer_created_cb preview_image_buffer_created_cb;
+ void *preview_image_buffer_created_cb_data;
+
+ capture_completed_cb capture_completed_cb;
+ void *capture_completed_cb_data;
+
+ bool is_af_enabled;
+};
+
+static struct __camera_data *g_camera_data = NULL;
+
+static const char * __cam_err_to_str(camera_error_e err)
+{
+ const char *err_str;
+
+ switch (err) {
+ case CAMERA_ERROR_NONE:
+ err_str = "CAMERA_ERROR_NONE";
+ break;
+ case CAMERA_ERROR_INVALID_PARAMETER:
+ err_str = "CAMERA_ERROR_INVALID_PARAMETER";
+ break;
+ case CAMERA_ERROR_INVALID_STATE:
+ err_str = "CAMERA_ERROR_INVALID_STATE";
+ break;
+ case CAMERA_ERROR_OUT_OF_MEMORY:
+ err_str = "CAMERA_ERROR_OUT_OF_MEMORY";
+ break;
+ case CAMERA_ERROR_DEVICE:
+ err_str = "CAMERA_ERROR_DEVICE";
+ break;
+ case CAMERA_ERROR_INVALID_OPERATION:
+ err_str = "CAMERA_ERROR_INVALID_OPERATION";
+ break;
+ case CAMERA_ERROR_SECURITY_RESTRICTED:
+ err_str = "CAMERA_ERROR_SECURITY_RESTRICTED";
+ break;
+ case CAMERA_ERROR_DEVICE_BUSY:
+ err_str = "CAMERA_ERROR_DEVICE_BUSY";
+ break;
+ case CAMERA_ERROR_DEVICE_NOT_FOUND:
+ err_str = "CAMERA_ERROR_DEVICE_NOT_FOUND";
+ break;
+ case CAMERA_ERROR_ESD:
+ err_str = "CAMERA_ERROR_ESD";
+ break;
+ case CAMERA_ERROR_PERMISSION_DENIED:
+ err_str = "CAMERA_ERROR_PERMISSION_DENIED";
+ break;
+ case CAMERA_ERROR_NOT_SUPPORTED:
+ err_str = "CAMERA_ERROR_NOT_SUPPORTED";
+ break;
+ case CAMERA_ERROR_RESOURCE_CONFLICT:
+ err_str = "CAMERA_ERROR_RESOURCE_CONFLICT";
+ break;
+ case CAMERA_ERROR_SERVICE_DISCONNECTED:
+ err_str = "CAMERA_ERROR_SERVICE_DISCONNECTED";
+ break;
+ default:
+ err_str = "Unknown";
+ break;
+ }
+ return err_str;
+}
+
+#ifdef DEBUG_THREAD
+static void __print_thread_id(char *msg)
+{
+ pthread_t id;
+ id = pthread_self();
+ _D("[%s] tid %u", msg, (unsigned int)id);
+}
+#endif
+
+static void __print_camera_state(camera_state_e previous, camera_state_e current, bool by_policy, void *user_data)
+{
+ switch (current) {
+ case CAMERA_STATE_CREATED:
+ _D("Camera state: CAMERA_STATE_CREATED");
+ break;
+
+ case CAMERA_STATE_PREVIEW:
+ _D("Camera state: CAMERA_STATE_PREVIEW");
+ break;
+
+ case CAMERA_STATE_CAPTURING:
+ _D("Camera state: CAMERA_STATE_CAPTURING");
+ break;
+
+ case CAMERA_STATE_CAPTURED:
+ _D("Camera state: CAMERA_STATE_CAPTURED");
+ break;
+
+ default:
+ _D("Camera state: CAMERA_STATE_NONE");
+ break;
+ }
+}
+
+static long long int __get_monotonic_ms(void)
+{
+ long long int ret_time = 0;
+ struct timespec time_s;
+
+ if (0 == clock_gettime(CLOCK_MONOTONIC, &time_s))
+ ret_time = time_s.tv_sec* 1000 + time_s.tv_nsec / 1000000;
+ else
+ _E("Failed to get time");
+
+ return ret_time;
+}
+
+static image_buffer_data_s *__make_preview_image_buffer_data(camera_preview_data_s *frame)
+{
+ unsigned char *buffer = NULL;
+ unsigned int buffer_size = 0;
+
+ image_buffer_data_s *image_buffer = malloc(sizeof(image_buffer_data_s));
+ if (image_buffer == NULL) {
+ _E("Failed to allocate image buffer data");
+ goto ERROR;
+ }
+
+ switch (frame->num_of_planes) {
+ case 1:
+ buffer_size = frame->data.single_plane.size;
+ buffer = malloc(buffer_size);
+ if (!buffer) {
+ _E("failed to malloc buffer");
+ goto ERROR;
+ }
+ memcpy(buffer, frame->data.single_plane.yuv, buffer_size);
+ break;
+ case 2:
+ {
+ unsigned char *buffer2 = NULL;
+ buffer_size =
+ frame->data.double_plane.y_size + frame->data.double_plane.uv_size;
+ buffer = malloc(buffer_size);
+ if (!buffer) {
+ _E("failed to malloc buffer");
+ goto ERROR;
+ }
+ buffer2 = buffer + frame->data.double_plane.y_size;
+ memcpy(buffer,
+ frame->data.double_plane.y, frame->data.double_plane.y_size);
+ memcpy(buffer2,
+ frame->data.double_plane.uv, frame->data.double_plane.uv_size);
+ }
+ break;
+ case 3:
+ {
+ unsigned char *buffer2 = NULL;
+ unsigned char *buffer3 = NULL;
+ buffer_size = frame->data.triple_plane.y_size
+ + frame->data.triple_plane.u_size
+ + frame->data.triple_plane.v_size;
+ buffer = malloc(buffer_size);
+ if (!buffer) {
+ _E("failed to malloc buffer");
+ goto ERROR;
+ }
+ buffer2 = buffer + frame->data.triple_plane.y_size;
+ buffer3 = buffer2 + frame->data.triple_plane.u_size;
+ memcpy(buffer,
+ frame->data.triple_plane.y, frame->data.triple_plane.y_size);
+ memcpy(buffer2,
+ frame->data.triple_plane.u, frame->data.triple_plane.u_size);
+ memcpy(buffer3,
+ frame->data.triple_plane.v, frame->data.triple_plane.v_size);
+ }
+ break;
+ default:
+ _E("unhandled num of planes : %d", frame->num_of_planes);
+ goto ERROR;
+ break;
+ }
+
+ image_buffer->image_width = frame->width;
+ image_buffer->image_height = frame->height;
+ image_buffer->buffer_size = buffer_size;
+ image_buffer->buffer = buffer;
+ image_buffer->format = frame->format;
+
+ return image_buffer;
+
+ERROR:
+ free(buffer);
+ free(image_buffer);
+
+ return NULL;
+}
+
+static bool __camera_attr_supported_af_mode_cb(camera_attr_af_mode_e mode, void *user_data)
+{
+ struct __camera_data *camera_data = user_data;
+
+ _I("Auto-Focus Mode [%d]", mode);
+
+ if (mode != CAMERA_ATTR_AF_NONE)
+ camera_data->is_af_enabled = true;
+
+ return true;
+}
+
+static void __capturing_cb(camera_image_data_s *image, camera_image_data_s *postview, camera_image_data_s *thumbnail, void *user_data)
+{
+ struct __camera_data *camera_data = user_data;
+ if (image == NULL) {
+ _E("Image is NULL");
+ return;
+ }
+
+ free(camera_data->captured_file);
+ camera_data->captured_file = malloc(image->size);
+ if (camera_data->captured_file == NULL)
+ return;
+
+ _D("Now is on Capturing: Image size[%d x %d]", image->width, image->height);
+
+ memcpy(camera_data->captured_file, image->data, image->size);
+ camera_data->image_size = image->size;
+
+ return;
+}
+
+static void __completed_cb(void *user_data)
+{
+ int ret = 0;
+ struct __camera_data *camera_data = user_data;
+
+ _D("Capture is completed");
+
+ if (camera_data->capture_completed_cb)
+ camera_data->capture_completed_cb(camera_data->captured_file, camera_data->image_size, camera_data->capture_completed_cb_data);
+
+ camera_data->capture_completed_cb = NULL;
+ free(camera_data->captured_file);
+ camera_data->captured_file = NULL;
+
+ if (!camera_data->cam_handle) {
+ _E("Camera is NULL");
+ return;
+ }
+
+ ret = camera_start_preview(camera_data->cam_handle);
+ if (ret != CAMERA_ERROR_NONE) {
+ _E("Failed to start preview [%s]", __cam_err_to_str(ret));
+ return;
+ }
+
+ return;
+}
+
+static void __start_capture(void *user_data)
+{
+ int ret = 0;
+ struct __camera_data *camera_data = user_data;
+
+ ret = camera_start_capture(camera_data->cam_handle, __capturing_cb, __completed_cb, camera_data);
+ if (ret != CAMERA_ERROR_NONE) {
+ _E("Failed to start capturing [%s]", __cam_err_to_str(ret));
+ return;
+ }
+}
+
+static void __camera_preview_cb(camera_preview_data_s *frame, void *user_data)
+{
+ struct __camera_data *camera_data = user_data;
+ static long long int last = 0;
+ long long int now = __get_monotonic_ms();
+
+ if (now - last < CAMERA_PREVIEW_INTERVAL_MIN)
+ return;
+
+ // _D("###Time Ellapse [%lld], [%lld], [%lld]", last, now, now - last);
+
+#ifdef DEBUG_THREAD
+ __print_thread_id("PREVIEW");
+#endif
+
+ image_buffer_data_s *image_buffer_data = __make_preview_image_buffer_data(frame);
+ if (image_buffer_data == NULL) {
+ _E("Failed to create mv source");
+ return;
+ }
+ image_buffer_data->user_data = camera_data->preview_image_buffer_created_cb_data;
+
+ ecore_main_loop_thread_safe_call_async(camera_data->preview_image_buffer_created_cb, image_buffer_data);
+ last = now;
+}
+
+int resource_camera_init(preview_image_buffer_created_cb preview_image_buffer_created_cb, void *user_data)
+{
+ int ret = CAMERA_ERROR_NONE;
+
+ if (preview_image_buffer_created_cb == NULL)
+ return -1;
+
+ g_camera_data = malloc(sizeof(struct __camera_data));
+ if (g_camera_data == NULL) {
+ _E("Failed to allocate Camera data");
+ return -1;
+ }
+ memset(g_camera_data, 0, sizeof(struct __camera_data));
+
+ ret = camera_create(CAMERA_DEVICE_CAMERA0, &(g_camera_data->cam_handle));
+ if (ret != CAMERA_ERROR_NONE) {
+ _E("Failed to create camera [%s]", __cam_err_to_str(ret));
+ goto ERROR;
+ }
+
+ ret = camera_attr_set_image_quality(g_camera_data->cam_handle, CAMERA_IMAGE_QUALITY);
+ if (ret != CAMERA_ERROR_NONE) {
+ _E("Failed to set image quality [%s]", __cam_err_to_str(ret));
+ goto ERROR;
+ }
+
+ ret = camera_set_preview_resolution(g_camera_data->cam_handle, IMAGE_WIDTH, IMAGE_HEIGHT);
+ if (ret != CAMERA_ERROR_NONE) {
+ _E("Failed to set preview resolution [%s]", __cam_err_to_str(ret));
+ goto ERROR;
+ }
+
+ ret = camera_set_capture_resolution(g_camera_data->cam_handle, IMAGE_WIDTH, IMAGE_HEIGHT);
+ if (ret != CAMERA_ERROR_NONE) {
+ _E("Failed to set capture resolution [%s]", __cam_err_to_str(ret));
+ goto ERROR;
+ }
+
+ ret = camera_set_capture_format(g_camera_data->cam_handle, CAMERA_PIXEL_FORMAT_JPEG);
+ if (ret != CAMERA_ERROR_NONE) {
+ _E("Failed to set capture format [%s]", __cam_err_to_str(ret));
+ goto ERROR;
+ }
+
+ ret = camera_set_state_changed_cb(g_camera_data->cam_handle, __print_camera_state, NULL);
+ if (ret != CAMERA_ERROR_NONE) {
+ _E("Failed to set state changed callback [%s]", __cam_err_to_str(ret));
+ goto ERROR;
+ }
+
+ ret = camera_set_preview_cb(g_camera_data->cam_handle, __camera_preview_cb, g_camera_data);
+ if (ret != CAMERA_ERROR_NONE) {
+ _E("Failed to set preview callback [%s]", __cam_err_to_str(ret));
+ goto ERROR;
+ }
+
+ ret = camera_attr_foreach_supported_af_mode(g_camera_data->cam_handle, __camera_attr_supported_af_mode_cb, g_camera_data);
+ if (ret != CAMERA_ERROR_NONE) {
+ _E("Failed to set auto focus attribute check callback [%s]", __cam_err_to_str(ret));
+ goto ERROR;
+ }
+
+ g_camera_data->preview_image_buffer_created_cb = preview_image_buffer_created_cb;
+ g_camera_data->preview_image_buffer_created_cb_data = user_data;
+
+ return 0;
+
+ERROR:
+ if (g_camera_data->cam_handle)
+ camera_destroy(g_camera_data->cam_handle);
+
+ free(g_camera_data);
+ g_camera_data = NULL;
+ return -1;
+}
+
+int resource_camera_start_preview(void)
+{
+ camera_state_e state;
+ int ret = CAMERA_ERROR_NONE;
+
+ if (g_camera_data == NULL) {
+ _I("Camera is not initialized");
+ return -1;
+ }
+
+ ret = camera_get_state(g_camera_data->cam_handle, &state);
+ if (ret != CAMERA_ERROR_NONE) {
+ _E("Failed to get camera state [%s]", __cam_err_to_str(ret));
+ return -1;
+ }
+
+ if (state == CAMERA_STATE_CAPTURING) {
+ _D("Camera is now capturing");
+ return -1;
+ }
+
+ if (state != CAMERA_STATE_PREVIEW) {
+ ret = camera_start_preview(g_camera_data->cam_handle);
+ if (ret != CAMERA_ERROR_NONE) {
+ _E("Failed to start preview [%s]", __cam_err_to_str(ret));
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+int resource_camera_capture(capture_completed_cb capture_completed_cb, void *user_data)
+{
+ camera_state_e state;
+ int ret = CAMERA_ERROR_NONE;
+
+ if (g_camera_data == NULL) {
+ _I("Camera is not initialized");
+ return -1;
+ }
+
+ ret = camera_get_state(g_camera_data->cam_handle, &state);
+ if (ret != CAMERA_ERROR_NONE) {
+ _E("Failed to get camera state [%s]", __cam_err_to_str(ret));
+ return -1;
+ }
+
+ if (state == CAMERA_STATE_CAPTURING) {
+ _D("Camera is now capturing");
+ return -1;
+ }
+
+ if (state != CAMERA_STATE_PREVIEW) {
+ _I("Preview is not started [%d]", state);
+ ret = camera_start_preview(g_camera_data->cam_handle);
+ if (ret != CAMERA_ERROR_NONE) {
+ _E("Failed to start preview [%s]", __cam_err_to_str(ret));
+ return -1;
+ }
+ }
+
+ __start_capture(g_camera_data);
+
+ g_camera_data->capture_completed_cb = capture_completed_cb;
+ g_camera_data->capture_completed_cb_data = user_data;
+
+ return 0;
+}
+
+void resource_camera_close(void)
+{
+ if (g_camera_data == NULL)
+ return;
+
+ camera_unset_preview_cb(g_camera_data->cam_handle);
+ camera_stop_preview(g_camera_data->cam_handle);
+
+ camera_destroy(g_camera_data->cam_handle);
+ g_camera_data->cam_handle = NULL;
+
+ free(g_camera_data->captured_file);
+ g_camera_data->captured_file = NULL;
+
+ free(g_camera_data);
+ g_camera_data = NULL;
+}
--- /dev/null
+ /*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ *
+ * 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 <peripheral_io.h>
+#include <glib.h>
+#include "log.h"
+
+#define ENABLE_SERVO_TIMEOUT
+
+/* This value is only for Servo Motor - SG90 */
+#define SERVO_MOTOR_DEFAULT_PERIOD 20.0
+#define SERVO_MOTOR_DUTY_CYCLE_COUNTER_CLOCKWISE 0.9
+#define SERVO_MOTOR_DUTY_CYCLE_CLOCKWISE 2.4
+
+#ifdef ENABLE_SERVO_TIMEOUT
+#define SERVO_TIMEOUT_INTERVAL 150
+#endif /* ENABLE_SERVO_TIMEOUT */
+
+/* This APIs are only made for Eagleye530s */
+/* There are 2 pins for PWM */
+static peripheral_pwm_h g_pwm0_h;
+static peripheral_pwm_h g_pwm2_h;
+
+#ifdef ENABLE_SERVO_TIMEOUT
+static guint g_timer_id0;
+static guint g_timer_id2;
+
+static gboolean __timeout_cb(void *data)
+{
+ int channel = GPOINTER_TO_INT(data);
+
+ _D("pwm channel[%d] disable", channel);
+ if (channel == 0 && g_pwm0_h) {
+ peripheral_pwm_set_enabled(g_pwm0_h, false);
+ g_timer_id0 = 0;
+ } else if (channel == 2 && g_pwm2_h) {
+ peripheral_pwm_set_enabled(g_pwm2_h, false);
+ g_timer_id2 = 0;
+ }
+ return FALSE;
+}
+
+static void __remove_timeout_cb(int channel)
+{
+ if (channel == 0) {
+ if (g_timer_id0) {
+ g_source_remove(g_timer_id0);
+ g_timer_id0 = 0;
+ }
+ } else if (channel == 2) {
+ if (g_timer_id2) {
+ g_source_remove(g_timer_id0);
+ g_timer_id2 = 0;
+ }
+ }
+}
+
+static void __add_timeout_cb(int channel)
+{
+ if (channel == 0) {
+ g_timer_id0 = g_timeout_add(SERVO_TIMEOUT_INTERVAL,
+ __timeout_cb, GINT_TO_POINTER(channel));
+ } else if (channel == 2) {
+ g_timer_id2 = g_timeout_add(SERVO_TIMEOUT_INTERVAL,
+ __timeout_cb, GINT_TO_POINTER(channel));
+ }
+}
+#endif /* ENABLE_SERVO_TIMEOUT */
+
+void resource_close_servo_motor(int channel)
+{
+#ifdef ENABLE_SERVO_TIMEOUT
+ __remove_timeout_cb(channel);
+#endif /* ENABLE_SERVO_TIMEOUT */
+
+ if (channel == 0 && g_pwm0_h) {
+ peripheral_pwm_close(g_pwm0_h);
+ g_pwm0_h = NULL;
+ } else if (channel == 2 && g_pwm2_h) {
+ peripheral_pwm_close(g_pwm2_h);
+ g_pwm2_h = NULL;
+ }
+}
+
+int resource_set_servo_motor_sg90_value(int channel, double duty_cycle_ms)
+{
+ int ret = 0;
+ peripheral_pwm_h *pwm_h = NULL;
+
+ if (duty_cycle_ms >= SERVO_MOTOR_DEFAULT_PERIOD) {
+ _E("Too large duty cycle");
+ return -1;
+ }
+
+#ifdef ENABLE_SERVO_TIMEOUT
+ __remove_timeout_cb(channel);
+#endif /* ENABLE_SERVO_TIMEOUT */
+
+ if (channel == 0) {
+ pwm_h = &g_pwm0_h;
+ } else if (channel == 2) {
+ pwm_h = &g_pwm2_h;
+ } else {
+ _E("unsupported channel - %d", channel);
+ return -1;
+ }
+
+ if (!*pwm_h) {
+ ret = peripheral_pwm_open(0, channel, pwm_h);
+ if (ret != PERIPHERAL_ERROR_NONE) {
+ _E("failed to open servo motor with channel(%d) : %s", channel, get_error_message(ret));
+ return -1;
+ }
+ }
+
+ ret = peripheral_pwm_set_period(*pwm_h, SERVO_MOTOR_DEFAULT_PERIOD * 1000 * 1000);
+ if (ret != PERIPHERAL_ERROR_NONE) {
+ _E("failed to set period : %s", get_error_message(ret));
+ return -1;
+ }
+
+ ret = peripheral_pwm_set_duty_cycle(*pwm_h, duty_cycle_ms * 1000 * 1000);
+ if (ret != PERIPHERAL_ERROR_NONE) {
+ _E("failed to set duty cycle : %s", get_error_message(ret));
+ return -1;
+ }
+
+ ret = peripheral_pwm_set_enabled(*pwm_h, true);
+ if (ret != PERIPHERAL_ERROR_NONE) {
+ _E("failed to enable : %s", get_error_message(ret));
+ return -1;
+ }
+
+#ifdef ENABLE_SERVO_TIMEOUT
+ __add_timeout_cb(channel);
+#endif /* ENABLE_SERVO_TIMEOUT */
+
+ return 0;
+}
+
+int resource_rotate_servo_motor_by_percent(int channel, double percent)
+{
+ int ret = 0;
+ double duty_cycle = 0.0f;
+
+ duty_cycle = ((SERVO_MOTOR_DUTY_CYCLE_CLOCKWISE - SERVO_MOTOR_DUTY_CYCLE_COUNTER_CLOCKWISE)
+ * (percent / 100.0))
+ + SERVO_MOTOR_DUTY_CYCLE_COUNTER_CLOCKWISE;
+
+ ret = resource_set_servo_motor_sg90_value(channel, duty_cycle);
+
+ return ret;
+}
--- /dev/null
+ /*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ *
+ * 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 <stdlib.h>
+#include <pthread.h>
+#include <glib.h>
+#include <math.h>
+#include "log.h"
+#include "servo-type.h"
+#include "resource_servo_motor_sg90.h"
+
+#define IDLE_PRIORITY (G_PRIORITY_HIGH_IDLE + 30)
+#define VALUE_DEFAULT (50.0f)
+#define SERVO_H_CHANNEL 2
+
+struct servo_h_data_s {
+ double value;
+ GHashTable *callback_hash;
+};
+
+struct servo_h_callback_s {
+ servo_state_changed_cb callback;
+ void *cb_data;
+};
+
+struct servo_h_pass_data_s {
+ char *pass_key;
+ double value;
+};
+
+static struct servo_h_data_s *g_servo_h;
+static pthread_mutex_t g_servo_h_mutex;
+
+static int __free_servo_h_handle(struct servo_h_data_s *servo_h)
+{
+ if (servo_h->callback_hash) {
+ g_hash_table_destroy(servo_h->callback_hash);
+ g_hash_table_unref(servo_h->callback_hash);
+ }
+
+ free(servo_h);
+ return 0;
+}
+
+int servo_h_finalize(void)
+{
+ if (g_servo_h) {
+ resource_close_servo_motor(SERVO_H_CHANNEL);
+ pthread_mutex_destroy(&g_servo_h_mutex);
+ __free_servo_h_handle(g_servo_h);
+ g_servo_h = NULL;
+ }
+ return 0;
+}
+
+int servo_h_initialize(void)
+{
+ if (g_servo_h) {
+ _D("The servo_h is already initialized!");
+ return 0;
+ }
+
+ g_servo_h = malloc(sizeof(struct servo_h_data_s));
+ retv_if(!g_servo_h, -1);
+
+ g_servo_h->callback_hash =
+ g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
+
+ pthread_mutex_init(&g_servo_h_mutex, NULL);
+ g_servo_h->value = VALUE_DEFAULT;
+
+ if (resource_rotate_servo_motor_by_percent(SERVO_H_CHANNEL, VALUE_DEFAULT)) {
+ _E("faiiled to set servo h value to 0");
+ servo_h_finalize();
+ return -1;
+ }
+
+ return 0;
+}
+
+static void __cb_item_foreach(gpointer key, gpointer value, gpointer user_data)
+{
+ char *item_name = key;
+ struct servo_h_callback_s *cb_item = value;
+ struct servo_h_pass_data_s *pass_item = user_data;
+
+ ret_if(!item_name);
+ ret_if(!cb_item);
+ ret_if(!pass_item);
+
+
+ if (pass_item->pass_key &&
+ (0 == g_strcmp0(item_name, pass_item->pass_key))) {
+ // _D("pass item - %s", item_name);
+ return;
+ }
+
+ _D("callback called for [%s]", item_name);
+ cb_item->callback(pass_item->value, cb_item->cb_data);
+}
+
+static gboolean __call_cb_idle(gpointer data)
+{
+ struct servo_h_pass_data_s *pass_item = data;
+
+ g_hash_table_foreach(g_servo_h->callback_hash, __cb_item_foreach, pass_item);
+ g_free(pass_item->pass_key);
+ g_free(pass_item);
+
+ return G_SOURCE_REMOVE;
+}
+
+static inline int __double_is_same(double a, double b)
+{
+ const double eps = 0.0001;
+ if (fabs(a-b) < eps)
+ return 1;
+ else
+ return 0;
+}
+
+int servo_h_state_set(double value, const char *pass_key)
+{
+ double old_value = 0.0;
+ retv_if(!g_servo_h, -1);
+
+ pthread_mutex_lock(&g_servo_h_mutex);
+ old_value = g_servo_h->value;
+ pthread_mutex_unlock(&g_servo_h_mutex);
+
+ if (!__double_is_same(old_value, value)) {
+ if (resource_rotate_servo_motor_by_percent(SERVO_H_CHANNEL, value)) {
+ _E("faiiled to set servo h value to [%lf]", value);
+ return -1;
+ }
+ _D("set value : %lf", value);
+ pthread_mutex_lock(&g_servo_h_mutex);
+ g_servo_h->value = value;
+ pthread_mutex_unlock(&g_servo_h_mutex);
+
+ if (g_hash_table_size(g_servo_h->callback_hash) > 0) {
+ struct servo_h_pass_data_s *pass_item = NULL;
+
+ pass_item = g_new(struct servo_h_pass_data_s, 1);
+ pass_item->pass_key = g_strdup(pass_key);
+ pass_item->value = value;
+ g_idle_add_full(IDLE_PRIORITY,
+ __call_cb_idle, pass_item, NULL);
+ }
+ } else {
+ _D("a value[%lf] is same as old one[%lf]" , value, old_value);
+ }
+ return 0;
+}
+
+int servo_h_state_get(double *value)
+{
+ retv_if(!g_servo_h, -1);
+ retv_if(!value, -1);
+
+ pthread_mutex_lock(&g_servo_h_mutex);
+ *value = g_servo_h->value;
+ pthread_mutex_unlock(&g_servo_h_mutex);
+
+ _D("get value : %lf", *value);
+
+ return 0;
+}
+
+int servo_h_state_changed_cb_set(
+ const char *callback_key, servo_state_changed_cb callback, void *cb_data)
+{
+ retv_if(!g_servo_h, -1);
+ retv_if(!g_servo_h->callback_hash, -1);
+ retv_if(!callback_key, -1);
+
+ if (callback) {
+ struct servo_h_callback_s *cb_item = NULL;
+ cb_item = g_try_new(struct servo_h_callback_s, 1);
+ retv_if(!cb_item, -1);
+
+ cb_item->callback = callback;
+ cb_item->cb_data = cb_data;
+
+ g_hash_table_insert(g_servo_h->callback_hash,
+ g_strdup(callback_key), cb_item);
+ } else {
+ g_hash_table_remove(g_servo_h->callback_hash, callback_key);
+ }
+
+ return 0;
+}
--- /dev/null
+ /*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ *
+ * 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 <stdlib.h>
+#include <pthread.h>
+#include <glib.h>
+#include <math.h>
+#include "log.h"
+#include "servo-type.h"
+#include "resource_servo_motor_sg90.h"
+
+#define IDLE_PRIORITY (G_PRIORITY_HIGH_IDLE + 30)
+#define VALUE_DEFAULT (50.0f)
+#define SERVO_V_CHANNEL 0
+
+struct servo_v_data_s {
+ double value;
+ GHashTable *callback_hash;
+};
+
+struct servo_v_callback_s {
+ servo_state_changed_cb callback;
+ void *cb_data;
+};
+
+struct servo_v_pass_data_s {
+ char *pass_key;
+ double value;
+};
+
+static struct servo_v_data_s *g_servo_v;
+static pthread_mutex_t g_servo_v_mutex;
+
+static int __free_servo_v_handle(struct servo_v_data_s *servo_v)
+{
+ if (servo_v->callback_hash) {
+ g_hash_table_destroy(servo_v->callback_hash);
+ g_hash_table_unref(servo_v->callback_hash);
+ }
+
+ free(servo_v);
+ return 0;
+}
+
+int servo_v_finalize(void)
+{
+ if (g_servo_v) {
+ resource_close_servo_motor(SERVO_V_CHANNEL);
+ pthread_mutex_destroy(&g_servo_v_mutex);
+ __free_servo_v_handle(g_servo_v);
+ g_servo_v = NULL;
+ }
+
+ return 0;
+}
+
+int servo_v_initialize(void)
+{
+ if (g_servo_v) {
+ _D("The servo_v is already initialized!");
+ return 0;
+ }
+
+ g_servo_v = malloc(sizeof(struct servo_v_data_s));
+ retv_if(!g_servo_v, -1);
+
+ g_servo_v->callback_hash =
+ g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
+
+ pthread_mutex_init(&g_servo_v_mutex, NULL);
+ g_servo_v->value = VALUE_DEFAULT;
+
+ if (resource_rotate_servo_motor_by_percent(SERVO_V_CHANNEL, VALUE_DEFAULT)) {
+ _E("faiiled to set servo h value to 0");
+ servo_v_finalize();
+ return -1;
+ }
+
+ return 0;
+}
+
+static void __cb_item_foreach(gpointer key, gpointer value, gpointer user_data)
+{
+ char *item_name = key;
+ struct servo_v_callback_s *cb_item = value;
+ struct servo_v_pass_data_s *pass_item = user_data;
+
+ ret_if(!item_name);
+ ret_if(!cb_item);
+ ret_if(!pass_item);
+
+ if (pass_item->pass_key &&
+ (0 == g_strcmp0(item_name, pass_item->pass_key))) {
+ // _D("pass item - %s", item_name);
+ return;
+ }
+
+ _D("callback called for [%s]", item_name);
+ cb_item->callback(pass_item->value, cb_item->cb_data);
+}
+
+static gboolean __call_cb_idle(gpointer data)
+{
+ struct servo_v_pass_data_s *pass_item = data;
+
+ g_hash_table_foreach(g_servo_v->callback_hash, __cb_item_foreach, pass_item);
+ g_free(pass_item->pass_key);
+ g_free(pass_item);
+
+ return G_SOURCE_REMOVE;
+}
+
+static inline int __double_is_same(double a, double b)
+{
+ const double eps = 0.0001;
+ if (fabs(a-b) < eps)
+ return 1;
+ else
+ return 0;
+}
+
+int servo_v_state_set(double value, const char *pass_key)
+{
+ double old_value = 0.0;
+ retv_if(!g_servo_v, -1);
+
+ pthread_mutex_lock(&g_servo_v_mutex);
+ old_value = g_servo_v->value;
+ pthread_mutex_unlock(&g_servo_v_mutex);
+
+ if (!__double_is_same(old_value, value)) {
+ if (resource_rotate_servo_motor_by_percent(SERVO_V_CHANNEL, value)) {
+ _E("faiiled to set servo v value to [%lf]", value);
+ return -1;
+ }
+ _D("set value : %lf", value);
+ pthread_mutex_lock(&g_servo_v_mutex);
+ g_servo_v->value = value;
+ pthread_mutex_unlock(&g_servo_v_mutex);
+
+ if (g_hash_table_size(g_servo_v->callback_hash) > 0) {
+ struct servo_v_pass_data_s *pass_item = NULL;
+
+ pass_item = g_new(struct servo_v_pass_data_s, 1);
+ pass_item->pass_key = g_strdup(pass_key);
+ pass_item->value = value;
+ g_idle_add_full(IDLE_PRIORITY,
+ __call_cb_idle, pass_item, NULL);
+ }
+ } else {
+ _D("a value[%lf] is same as old one[%lf]" , value, old_value);
+ }
+ return 0;
+}
+
+int servo_v_state_get(double *value)
+{
+ retv_if(!g_servo_v, -1);
+ retv_if(!value, -1);
+
+ pthread_mutex_lock(&g_servo_v_mutex);
+ *value = g_servo_v->value;
+ pthread_mutex_unlock(&g_servo_v_mutex);
+
+ _D("get value : %lf", *value);
+
+ return 0;
+}
+
+int servo_v_state_changed_cb_set(
+ const char *callback_key, servo_state_changed_cb callback, void *cb_data)
+{
+ retv_if(!g_servo_v, -1);
+ retv_if(!g_servo_v->callback_hash, -1);
+ retv_if(!callback_key, -1);
+
+ if (callback) {
+ struct servo_v_callback_s *cb_item = NULL;
+ cb_item = g_try_new(struct servo_v_callback_s, 1);
+ retv_if(!cb_item, -1);
+
+ cb_item->callback = callback;
+ cb_item->cb_data = cb_data;
+
+ g_hash_table_insert(g_servo_v->callback_hash,
+ g_strdup(callback_key), cb_item);
+ } else {
+ g_hash_table_remove(g_servo_v->callback_hash, callback_key);
+ }
+
+ return 0;
+}
--- /dev/null
+ /*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ *
+ * 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 <smartthings.h>
+#include "log.h"
+
+/* You have to FIX IT !!! */
+#define CERT_FILE "cert_file_name.pem" // cert file name in 'res' directory
+#define PRIV_FILE "private_key_file_name.der" // private key file name in 'res' directory
+
+static smartthings_h g_st_master_h;
+
+static void _user_confirm_cb(smartthings_h handle, void *user_data)
+{
+ if (smartthings_send_user_confirm(handle, true) != 0)
+ _E("smartthings_send_user_confirm() is failed");
+}
+
+static void _reset_confirm_cb(smartthings_h handle, void *user_data)
+{
+ if (smartthings_send_reset_confirm(handle, true) != 0)
+ _E("smartthings_send_reset_confirm() is failed");
+}
+
+static void _reset_result_cb(smartthings_h handle, bool result, void *user_data)
+{
+ _I("reset result = [%d]", result);
+}
+
+static const char *thing_status_to_str(smartthings_status_e status)
+{
+ const char *status_str = NULL;
+
+ switch (status) {
+ case SMARTTHINGS_STATUS_NOT_READY:
+ status_str = "SMARTTHINGS_STATUS_NOT_READY";
+ break;
+ case SMARTTHINGS_STATUS_INIT:
+ status_str = "SMARTTHINGS_STATUS_INIT";
+ break;
+ case SMARTTHINGS_STATUS_ES_STARTED:
+ status_str = "SMARTTHINGS_STATUS_ES_STARTED";
+ break;
+ case SMARTTHINGS_STATUS_ES_DONE:
+ status_str = "SMARTTHINGS_STATUS_ES_DONE";
+ break;
+ case SMARTTHINGS_STATUS_ES_FAILED_ON_OWNERSHIP_TRANSFER:
+ status_str = "SMARTTHINGS_STATUS_ES_FAILED_ON_OWNERSHIP_TRANSFER";
+ break;
+ case SMARTTHINGS_STATUS_CONNECTING_TO_AP:
+ status_str = "SMARTTHINGS_STATUS_CONNECTING_TO_AP";
+ break;
+ case SMARTTHINGS_STATUS_CONNECTED_TO_AP:
+ status_str = "SMARTTHINGS_STATUS_CONNECTED_TO_AP";
+ break;
+ case SMARTTHINGS_STATUS_CONNECTING_TO_AP_FAILED:
+ status_str = "SMARTTHINGS_STATUS_CONNECTING_TO_AP_FAILED";
+ break;
+ case SMARTTHINGS_STATUS_REGISTERING_TO_CLOUD:
+ status_str = "SMARTTHINGS_STATUS_REGISTERING_TO_CLOUD";
+ break;
+ case SMARTTHINGS_STATUS_REGISTERED_TO_CLOUD:
+ status_str = "SMARTTHINGS_STATUS_REGISTERED_TO_CLOUD";
+ break;
+ case SMARTTHINGS_STATUS_REGISTERING_FAILED_ON_SIGN_IN:
+ status_str = "SMARTTHINGS_STATUS_REGISTERING_FAILED_ON_SIGN_IN";
+ break;
+ case SMARTTHINGS_STATUS_REGISTERING_FAILED_ON_PUB_RES:
+ status_str = "SMARTTHINGS_STATUS_REGISTERING_FAILED_ON_PUB_RES";
+ break;
+ default:
+ status_str = "Unknown Status";
+ break;
+ }
+ return status_str;
+}
+
+static void
+_thing_status_cb(
+ smartthings_h handle, smartthings_status_e status, void *user_data)
+{
+ _D("status: [%d] [%s]", status, thing_status_to_str(status));
+}
+
+static const char *__master_error_to_str(smartthings_error_e error)
+{
+ const char *err_str = NULL;
+
+ switch (error) {
+ case SMARTTHINGS_ERROR_NONE:
+ err_str = "SMARTTHINGS_ERROR_NONE";
+ break;
+ case SMARTTHINGS_ERROR_INVALID_PARAMETER:
+ err_str = "SMARTTHINGS_ERROR_INVALID_PARAMETER";
+ break;
+ case SMARTTHINGS_ERROR_OUT_OF_MEMORY:
+ err_str = "SMARTTHINGS_ERROR_OUT_OF_MEMORY";
+ break;
+ case SMARTTHINGS_ERROR_PERMISSION_DENIED:
+ err_str = "SMARTTHINGS_ERROR_PERMISSION_DENIED";
+ break;
+ case SMARTTHINGS_ERROR_NO_DATA:
+ err_str = "SMARTTHINGS_ERROR_NO_DATA";
+ break;
+ case SMARTTHINGS_ERROR_NOT_SUPPORTED:
+ err_str = "SMARTTHINGS_ERROR_NOT_SUPPORTED";
+ break;
+ case SMARTTHINGS_ERROR_OPERATION_FAILED:
+ err_str = "SMARTTHINGS_ERROR_OPERATION_FAILED";
+ break;
+ case SMARTTHINGS_ERROR_SERVICE_UNAVAILABLE:
+ err_str = "SMARTTHINGS_ERROR_SERVICE_UNAVAILABLE";
+ break;
+ default:
+ err_str = "Unknown error";
+ break;
+ }
+
+ return err_str;
+}
+
+static void
+_things_connection_status_cb(smartthings_error_e error,
+ smartthings_h handle, smartthings_connection_status_e status,
+ void *user_data)
+{
+ _D("result [%s], status = [%d]", __master_error_to_str(error), status);
+
+ if (status == SMARTTHINGS_CONNECTION_STATUS_CONNECTED) {
+ int err = 0;
+ bool is_es_completed = false;
+ const char* dev_name = "iot-vision-cam";
+ int wifi_mode = SMARTTHINGS_WIFI_MODE_11B
+ | SMARTTHINGS_WIFI_MODE_11G
+ | SMARTTHINGS_WIFI_MODE_11N;
+
+ int wifi_freq = SMARTTHINGS_WIFI_FREQ_24G | SMARTTHINGS_WIFI_FREQ_5G;
+
+ err = smartthings_set_device_property(
+ handle, dev_name, wifi_mode, wifi_freq);
+ if (err) {
+ _E("smartthings_initialize() is failed, [%s]",
+ __master_error_to_str(err));
+ return;
+ }
+
+ err = smartthings_set_certificate_file(handle, CERT_FILE, PRIV_FILE);
+ if (err) {
+ _E("smartthings_set_certificate_file() is failed, [%s]",
+ __master_error_to_str(err));
+ return;
+ }
+
+ err = smartthings_set_user_confirm_cb(handle, _user_confirm_cb, NULL);
+ if (err) {
+ _E("smartthings_set_user_confirm_cb() is failed, [%s]",
+ __master_error_to_str(err));
+ return;
+ }
+
+ err = smartthings_set_reset_confirm_cb(handle, _reset_confirm_cb, NULL);
+ if (err) {
+ _E("smartthings_set_reset_confirm_cb() is failed, [%s]",
+ __master_error_to_str(err));
+ return;
+ }
+
+ err = smartthings_set_reset_result_cb(handle, _reset_result_cb, NULL);
+ if (err) {
+ _E("smartthings_set_reset_confirm_cb() is failed, [%s]",
+ __master_error_to_str(err));
+ return;
+ }
+
+ err = smartthings_set_status_changed_cb(handle, _thing_status_cb, NULL);
+ if (err) {
+ _E("smartthings_set_status_changed_callback() is failed, [%s]",
+ __master_error_to_str(err));
+ return;
+ }
+
+ err = smartthings_start(handle);
+ if (err) {
+ _E("smartthings_start() is failed, [%s]",
+ __master_error_to_str(err));
+ return;
+ }
+
+ err = smartthings_get_easysetup_status(handle, &is_es_completed);
+ if (err) {
+ _E("smartthings_get_easysetup_status() is failed, [%s]",
+ __master_error_to_str(err));
+ return;
+ }
+
+ if (is_es_completed == true) {
+ _I("Easysetup is already done");
+ return;
+ }
+
+ err = smartthings_start_easysetup(handle);
+ if (err) {
+ _E("smartthings_start_easysetup() is failed, [%s]",
+ __master_error_to_str(err));
+ smartthings_stop(handle);
+ return;
+ }
+ } else {
+ _E("connection failed");
+ }
+ return;
+}
+
+int st_thing_master_init()
+{
+ int err = 0;
+ smartthings_h st_handle = NULL;
+
+ if (g_st_master_h) {
+ _I("Already initialized!");
+ return 0;
+ }
+
+ err = smartthings_initialize(&st_handle, _things_connection_status_cb, NULL);
+ if (err) {
+ _E("smartthings_initialize() is failed, [%s]",
+ __master_error_to_str(err));
+ return -1;
+ }
+
+ g_st_master_h = st_handle;
+
+ return 0;
+}
+
+int st_thing_master_fini()
+{
+ if (!g_st_master_h) {
+ _I("handle is already NULL");
+ return 0;
+ }
+
+ smartthings_unset_user_confirm_cb(g_st_master_h);
+ smartthings_unset_reset_confirm_cb(g_st_master_h);
+ smartthings_unset_reset_result_cb(g_st_master_h);
+ smartthings_unset_status_changed_cb(g_st_master_h);
+
+ smartthings_stop_easysetup(g_st_master_h);
+ smartthings_stop(g_st_master_h);
+
+ if (smartthings_deinitialize(g_st_master_h) != 0) {
+ _E("smartthings_deinitialize() is failed");
+ return -1;
+ }
+ g_st_master_h = NULL;
+
+ return 0;
+}
--- /dev/null
+ /*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ *
+ * 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 <smartthings_resource.h>
+#include <smartthings_payload.h>
+#include <glib.h>
+#include "log.h"
+#include "switch.h"
+#include "servo-h.h"
+#include "servo-v.h"
+#include "motion.h"
+
+// switch
+#define URI_SWITCH "/capability/switch/main/0"
+#define KEY_SWITCH "power"
+#define VALUE_SWITCH_ON "on"
+#define VALUE_SWITCH_OFF "off"
+
+// volume - servo v
+#define URI_AUDIOVOLUME "/capability/audioVolume/main/0"
+#define KEY_VOLUME "volume"
+#define KEY_MUTE "mute"
+
+// dim switch - servo h
+#define URI_SWITCHLEVEL "/capability/switchLevel/main/0"
+#define KEY_SWITCHLEVEL "dimmingSetting"
+
+// motion
+#define URI_MOTION "/capability/motionSensor/main/0"
+#define KEY_MOTION "value"
+
+#define RESOURCE_CALLBACK_KEY "st_thing_resource"
+
+static smartthings_resource_h g_st_res_h;
+static smartthings_resource_connection_status_e g_conn_status =
+ SMARTTHINGS_RESOURCE_CONNECTION_STATUS_DISCONNECTED;
+
+
+static const char *
+__resource_error_to_str(smartthings_resource_error_e error)
+{
+ const char *err_str = NULL;
+
+ switch (error) {
+ case SMARTTHINGS_RESOURCE_ERROR_NONE:
+ err_str = "SMARTTHINGS_RESOURCE_ERROR_NONE";
+ break;
+ case SMARTTHINGS_RESOURCE_ERROR_INVALID_PARAMETER:
+ err_str = "SMARTTHINGS_RESOURCE_ERROR_INVALID_PARAMETER";
+ break;
+ case SMARTTHINGS_RESOURCE_ERROR_OUT_OF_MEMORY:
+ err_str = "SMARTTHINGS_RESOURCE_ERROR_OUT_OF_MEMORY";
+ break;
+ case SMARTTHINGS_RESOURCE_ERROR_PERMISSION_DENIED:
+ err_str = "SMARTTHINGS_RESOURCE_ERROR_PERMISSION_DENIED";
+ break;
+ case SMARTTHINGS_RESOURCE_ERROR_NO_DATA:
+ err_str = "SMARTTHINGS_RESOURCE_ERROR_NO_DATA";
+ break;
+ case SMARTTHINGS_RESOURCE_ERROR_NOT_SUPPORTED:
+ err_str = "SMARTTHINGS_RESOURCE_ERROR_NOT_SUPPORTED";
+ break;
+ case SMARTTHINGS_RESOURCE_ERROR_OPERATION_FAILED:
+ err_str = "SMARTTHINGS_RESOURCE_ERROR_NOT_SUPPORTED";
+ break;
+ case SMARTTHINGS_RESOURCE_ERROR_SERVICE_UNAVAILABLE:
+ err_str = "SMARTTHINGS_RESOURCE_ERROR_SERVICE_UNAVAILABLE";
+ break;
+ default:
+ err_str = "Unknown error";
+ break;
+ }
+
+ return err_str;
+}
+
+/* get and set request handlers */
+static bool
+handle_get_motion(smartthings_payload_h resp_payload, void *user_data)
+{
+ int state = 0;
+
+ motion_state_get(&state);
+
+ _D("GET request for motion : %d", state);
+ smartthings_payload_set_bool(resp_payload, KEY_MOTION, state ? true : false);
+
+ return true;
+}
+
+static bool
+handle_set_motion(smartthings_payload_h payload,
+ smartthings_payload_h resp_payload, void *user_data)
+{
+ bool bvalue = 0;
+
+ if (smartthings_payload_get_bool(payload, KEY_MOTION, &bvalue) == 0) {
+ _D("requested volume: [%d]", bvalue);
+ motion_state_set((int)bvalue, RESOURCE_CALLBACK_KEY);
+ smartthings_payload_set_bool(resp_payload, KEY_MOTION, bvalue);
+ }
+
+ return true;
+}
+
+static bool
+handle_get_switch(smartthings_payload_h resp_payload, void *user_data)
+{
+ switch_state_e state = SWITCH_STATE_OFF;
+ const char *switch_state_name = NULL;
+
+ switch_state_get(&state);
+
+ if (state == SWITCH_STATE_OFF)
+ switch_state_name = VALUE_SWITCH_OFF;
+ else
+ switch_state_name = VALUE_SWITCH_ON;
+
+ _D("GET request for switch : %s", switch_state_name);
+ smartthings_payload_set_string(resp_payload, KEY_SWITCH, switch_state_name);
+
+ return true;
+}
+
+static bool
+handle_set_switch(smartthings_payload_h payload,
+ smartthings_payload_h resp_payload, void *user_data)
+{
+ char *str_value = NULL;
+ switch_state_e state = SWITCH_STATE_OFF;
+
+ if (smartthings_payload_get_string(payload, KEY_SWITCH, &str_value) != 0) {
+ _E("failed to smartthings_payload_get_string()");
+ return false;
+ }
+ retv_if(!str_value, false);
+
+ _D("SET request for switch: [%s]", str_value);
+
+ if (0 == g_strcmp0(str_value, VALUE_SWITCH_ON))
+ state = SWITCH_STATE_ON;
+
+ switch_state_set(state, RESOURCE_CALLBACK_KEY);
+
+ smartthings_payload_set_string(resp_payload, KEY_SWITCH, str_value);
+ free(str_value);
+
+ return true;
+}
+
+static bool
+handle_get_audiovolume(smartthings_payload_h resp_payload, void *user_data)
+{
+ double value = 0.0f;
+
+ servo_v_state_get(&value);
+
+ _D("current volume: [%f]", value);
+ smartthings_payload_set_int(resp_payload, KEY_VOLUME, (int)value);
+ smartthings_payload_set_bool(resp_payload, KEY_MUTE, false);
+
+ return true;
+}
+
+static bool
+handle_set_audiovolume(smartthings_payload_h payload,
+ smartthings_payload_h resp_payload, void *user_data)
+{
+ int ivalue = 0;
+
+ if (smartthings_payload_get_int(payload, KEY_VOLUME, &ivalue) == 0) {
+ _D("requested volume: [%d]", ivalue);
+ servo_v_state_set((double)ivalue, RESOURCE_CALLBACK_KEY);
+ smartthings_payload_set_int(resp_payload, KEY_VOLUME, ivalue);
+ }
+
+ smartthings_payload_set_bool(resp_payload, KEY_MUTE, false);
+
+ return true;
+}
+
+static bool
+handle_get_switchLevel(smartthings_payload_h resp_payload, void *user_data)
+{
+
+ double value = 0;
+
+ servo_h_state_get(&value);
+
+ _D("current switchLevel: [%f]", value);
+ smartthings_payload_set_int(resp_payload, KEY_SWITCHLEVEL, (int)value);
+
+ return true;
+
+}
+
+static bool
+handle_set_switchLevel(smartthings_payload_h payload,
+ smartthings_payload_h resp_payload, void *user_data)
+{
+ int ivalue = 0;
+
+ if (smartthings_payload_get_int(payload, KEY_SWITCHLEVEL, &ivalue) == 0) {
+ _D("requested dimming: [%d]", ivalue);
+ servo_h_state_set((double)ivalue, RESOURCE_CALLBACK_KEY);
+ smartthings_payload_set_int(resp_payload, KEY_SWITCHLEVEL, ivalue);
+ }
+
+ return true;
+}
+
+static void
+_request_cb(smartthings_resource_h handle, int req_id,
+ const char *uri, smartthings_resource_req_type_e req_type,
+ smartthings_payload_h payload, void *user_data)
+{
+ smartthings_payload_h resp_payload = NULL;
+ bool result = false;
+ int error = SMARTTHINGS_RESOURCE_ERROR_NONE;
+
+ _D("request on %s, type[%d], id[%d]", uri, req_type, req_id);
+
+ smartthings_payload_create(&resp_payload);
+ if (!resp_payload) {
+ _E("Response payload is NULL");
+ return;
+ }
+
+ if (req_type == SMARTTHINGS_RESOURCE_REQUEST_GET) {
+ if (0 == g_strcmp0(uri, URI_SWITCH))
+ result = handle_get_switch(resp_payload, user_data);
+ else if (0 == g_strcmp0(uri, URI_AUDIOVOLUME))
+ result = handle_get_audiovolume(resp_payload, user_data);
+ else if (0 == g_strcmp0(uri, URI_SWITCHLEVEL))
+ result = handle_get_switchLevel(resp_payload, user_data);
+ else if (0 == g_strcmp0(uri, URI_MOTION))
+ result = handle_get_motion(resp_payload, user_data);
+ else
+ _E("No matching Resource uri");
+ } else if (req_type == SMARTTHINGS_RESOURCE_REQUEST_SET) {
+ if (0 == g_strcmp0(uri, URI_SWITCH))
+ result = handle_set_switch(payload, resp_payload, user_data);
+ else if (0 == g_strcmp0(uri, URI_AUDIOVOLUME))
+ result = handle_set_audiovolume(payload, resp_payload, user_data);
+ else if (0 == g_strcmp0(uri, URI_SWITCHLEVEL))
+ result = handle_set_switchLevel(payload, resp_payload, user_data);
+ else if (0 == g_strcmp0(uri, URI_MOTION))
+ result = handle_set_motion(payload, resp_payload, user_data);
+ else
+ _E("No matching Resource uri");
+ } else {
+ _E("Invalid request type - %d", req_type);
+ smartthings_payload_destroy(resp_payload);
+ return;
+ }
+
+ error = smartthings_resource_send_response(handle, req_id, uri, resp_payload, result);
+ if (error != SMARTTHINGS_RESOURCE_ERROR_NONE) {
+ smartthings_payload_destroy(resp_payload);
+ _E("smartthings_resource_send_response() failed, [%s]",
+ __resource_error_to_str(error));
+ return;
+ }
+
+ if (req_type == SMARTTHINGS_RESOURCE_REQUEST_SET) {
+ error = smartthings_resource_notify(handle, uri, resp_payload);
+ if (error != SMARTTHINGS_RESOURCE_ERROR_NONE)
+ _E("smartthings_resource_notify() failed, [%s]",
+ __resource_error_to_str(error));
+ }
+
+ if (smartthings_payload_destroy(resp_payload))
+ _E("smartthings_payload_destroy failed");
+
+ return;
+}
+
+static void
+_resource_connection_status_cb(smartthings_resource_error_e error,
+ smartthings_resource_h handle,
+ smartthings_resource_connection_status_e status, void *user_data)
+{
+ _D("result [%s], status=[%d]", __resource_error_to_str(error), status);
+
+ g_conn_status = status;
+
+ if (status == SMARTTHINGS_RESOURCE_CONNECTION_STATUS_CONNECTED) {
+ if (smartthings_resource_set_request_cb(handle, _request_cb, NULL)) {
+ _E("smartthings_resource_set_request_cb() is failed");
+ return;
+ }
+ } else {
+ _E("connection failed");
+ }
+ return;
+}
+
+static void __motion_changed(int value, void* user_data)
+{
+ smartthings_resource_h handle = user_data;
+ smartthings_payload_h payload = NULL;
+ int error = SMARTTHINGS_RESOURCE_ERROR_NONE;
+
+ ret_if(!handle);
+
+ _D("motion changed to - %d", value);
+
+ ret_if(g_conn_status != SMARTTHINGS_RESOURCE_CONNECTION_STATUS_CONNECTED);
+
+ smartthings_payload_create(&payload);
+ if (!payload) {
+ _E("failed to create payload is NULL");
+ return;
+ }
+
+ smartthings_payload_set_bool(payload, KEY_MOTION, value ? true : false);
+
+ error = smartthings_resource_notify(handle, URI_MOTION, payload);
+ if (error != SMARTTHINGS_RESOURCE_ERROR_NONE)
+ _E("smartthings_resource_notify() failed, [%s]",
+ __resource_error_to_str(error));
+
+ smartthings_payload_destroy(payload);
+}
+
+static void __switch_changed(switch_state_e state, void* user_data)
+{
+ smartthings_resource_h handle = user_data;
+ smartthings_payload_h payload = NULL;
+ int error = SMARTTHINGS_RESOURCE_ERROR_NONE;
+ const char *switch_state_name = NULL;
+
+ _D("switch changed to - %d", state);
+ ret_if(!handle);
+ ret_if(g_conn_status != SMARTTHINGS_RESOURCE_CONNECTION_STATUS_CONNECTED);
+
+ smartthings_payload_create(&payload);
+ if (!payload) {
+ _E("failed to create payload is NULL");
+ return;
+ }
+
+ if (state == SWITCH_STATE_OFF)
+ switch_state_name = VALUE_SWITCH_OFF;
+ else
+ switch_state_name = VALUE_SWITCH_ON;
+
+ smartthings_payload_set_string(payload, KEY_SWITCH, switch_state_name);
+
+ error = smartthings_resource_notify(handle, URI_SWITCH, payload);
+ if (error != SMARTTHINGS_RESOURCE_ERROR_NONE)
+ _E("smartthings_resource_notify() failed, [%s]",
+ __resource_error_to_str(error));
+
+ smartthings_payload_destroy(payload);
+}
+
+static void __servo_v_changed(double value, void* user_data)
+{
+ smartthings_resource_h handle = user_data;
+ smartthings_payload_h payload = NULL;
+ int error = SMARTTHINGS_RESOURCE_ERROR_NONE;
+
+ _D("servo_v changed to - %f", value);
+ ret_if(!handle);
+ ret_if(g_conn_status != SMARTTHINGS_RESOURCE_CONNECTION_STATUS_CONNECTED);
+
+ smartthings_payload_create(&payload);
+ if (!payload) {
+ _E("failed to create payload is NULL");
+ return;
+ }
+
+ smartthings_payload_set_int(payload, KEY_VOLUME, (int)value);
+
+ error = smartthings_resource_notify(handle, URI_AUDIOVOLUME, payload);
+ if (error != SMARTTHINGS_RESOURCE_ERROR_NONE)
+ _E("smartthings_resource_notify() failed, [%s]",
+ __resource_error_to_str(error));
+
+ smartthings_payload_destroy(payload);
+}
+
+static void __servo_h_changed(double value, void* user_data)
+{
+ smartthings_resource_h handle = user_data;
+ smartthings_payload_h payload = NULL;
+ int error = SMARTTHINGS_RESOURCE_ERROR_NONE;
+
+ _D("servo_h changed to - %f", value);
+ ret_if(!handle);
+ ret_if(g_conn_status != SMARTTHINGS_RESOURCE_CONNECTION_STATUS_CONNECTED);
+
+ smartthings_payload_create(&payload);
+ if (!payload) {
+ _E("failed to create payload is NULL");
+ return;
+ }
+
+ smartthings_payload_set_int(payload, KEY_SWITCHLEVEL, (int)value);
+
+ error = smartthings_resource_notify(handle, URI_SWITCHLEVEL, payload);
+ if (error != SMARTTHINGS_RESOURCE_ERROR_NONE)
+ _E("smartthings_resource_notify() failed, [%s]",
+ __resource_error_to_str(error));
+
+ smartthings_payload_destroy(payload);
+}
+
+static int __device_interfaces_set_callbak(smartthings_resource_h handle)
+{
+ retv_if(!handle, -1);
+
+ // Assume that, device interfaces are already initialized in controller.c
+ switch_state_changed_cb_set(RESOURCE_CALLBACK_KEY,
+ __switch_changed, handle);
+ servo_v_state_changed_cb_set(RESOURCE_CALLBACK_KEY,
+ __servo_v_changed, handle);
+ servo_h_state_changed_cb_set(RESOURCE_CALLBACK_KEY,
+ __servo_h_changed, handle);
+ motion_state_changed_cb_set(RESOURCE_CALLBACK_KEY,
+ __motion_changed, handle);
+
+ return 0;
+}
+
+
+int st_thing_resource_init(void)
+{
+ smartthings_resource_h st_res_h = NULL;
+ int error = 0;
+
+ if (g_st_res_h) {
+ _I("Already initialized!");
+ return 0;
+ }
+
+ error = smartthings_resource_initialize(&st_res_h,
+ _resource_connection_status_cb, NULL);
+ if (error) {
+ _E("smartthings_resource_initialize() is failed, [%s]",
+ __resource_error_to_str(error));
+ return -1;
+ }
+
+ g_st_res_h = st_res_h;
+ g_conn_status = SMARTTHINGS_RESOURCE_CONNECTION_STATUS_DISCONNECTED;
+
+ __device_interfaces_set_callbak(g_st_res_h);
+
+ return 0;
+}
+
+int st_thing_resource_fini(void)
+{
+ if (!g_st_res_h)
+ return 0;
+
+ smartthings_resource_unset_request_cb(g_st_res_h);
+ smartthings_resource_deinitialize(g_st_res_h);
+ g_st_res_h = NULL;
+ g_conn_status = SMARTTHINGS_RESOURCE_CONNECTION_STATUS_DISCONNECTED;
+
+ return 0;
+}
--- /dev/null
+ /*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ *
+ * 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 <stdlib.h>
+#include <pthread.h>
+#include <glib.h>
+#include "log.h"
+#include "switch.h"
+
+#define IDLE_PRIORITY (G_PRIORITY_HIGH_IDLE + 30)
+
+struct switch_data_s {
+ switch_state_e state;
+ GHashTable *callback_hash;
+};
+
+struct switch_callback_s {
+ switch_state_changed_cb callback;
+ void *cb_data;
+};
+
+struct switch_pass_data_s {
+ char *pass_key;
+ switch_state_e state;
+};
+
+static struct switch_data_s *g_switch;
+static pthread_mutex_t g_switch_mutex;
+
+static int __free_switch_handle(struct switch_data_s *sw)
+{
+ if (sw->callback_hash) {
+ g_hash_table_destroy(sw->callback_hash);
+ g_hash_table_unref(sw->callback_hash);
+ }
+
+ free(sw);
+ return 0;
+}
+
+int switch_initialize(void)
+{
+ if (g_switch) {
+ _D("The switch is already initialized!");
+ return 0;
+ }
+
+ g_switch = malloc(sizeof(struct switch_data_s));
+ retv_if(!g_switch, -1);
+
+ g_switch->callback_hash =
+ g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
+
+ pthread_mutex_init(&g_switch_mutex, NULL);
+ g_switch->state = SWITCH_STATE_OFF;
+
+ /* TODO : initialize real switch here */
+
+ return 0;
+}
+
+int switch_finalize(void)
+{
+ if (g_switch) {
+ pthread_mutex_destroy(&g_switch_mutex);
+ __free_switch_handle(g_switch);
+ g_switch = NULL;
+ }
+
+ return 0;
+}
+
+static void __cb_item_foreach(gpointer key, gpointer value, gpointer user_data)
+{
+ char *item_name = key;
+ struct switch_callback_s *cb_item = value;
+ struct switch_pass_data_s *pass_item = user_data;
+
+ ret_if(!item_name);
+ ret_if(!cb_item);
+ ret_if(!pass_item);
+
+
+ if (pass_item->pass_key &&
+ (0 == g_strcmp0(item_name, pass_item->pass_key))) {
+ // _D("pass item - %s", item_name);
+ return;
+ }
+
+ _D("callback called for [%s]", item_name);
+ cb_item->callback(pass_item->state, cb_item->cb_data);
+}
+
+static gboolean __call_cb_idle(gpointer data)
+{
+ struct switch_pass_data_s *pass_item = data;
+
+ g_hash_table_foreach(g_switch->callback_hash, __cb_item_foreach, pass_item);
+ g_free(pass_item->pass_key);
+ g_free(pass_item);
+
+ return G_SOURCE_REMOVE;
+}
+
+int switch_state_set(switch_state_e state, const char *pass_key)
+{
+ int old_state = 0;
+ retv_if(!g_switch, -1);
+
+ pthread_mutex_lock(&g_switch_mutex);
+ old_state = g_switch->state;
+ pthread_mutex_unlock(&g_switch_mutex);
+
+ if (old_state != state) {
+ pthread_mutex_lock(&g_switch_mutex);
+ g_switch->state = state;
+ pthread_mutex_unlock(&g_switch_mutex);
+
+ if (g_hash_table_size(g_switch->callback_hash) > 0) {
+ struct switch_pass_data_s *pass_item = NULL;
+
+ pass_item = g_new(struct switch_pass_data_s, 1);
+ pass_item->pass_key = g_strdup(pass_key);
+ pass_item->state = state;
+ g_idle_add_full(IDLE_PRIORITY,
+ __call_cb_idle, pass_item, NULL);
+ }
+ }
+ return 0;
+}
+
+int switch_state_get(switch_state_e *state)
+{
+ retv_if(!g_switch, -1);
+ retv_if(!state, -1);
+
+ pthread_mutex_lock(&g_switch_mutex);
+ *state = g_switch->state;
+ pthread_mutex_unlock(&g_switch_mutex);
+
+ // _D("get state : %d", *state);
+
+ return 0;
+}
+
+int switch_state_changed_cb_set(
+ const char *callback_key, switch_state_changed_cb callback, void *cb_data)
+{
+ retv_if(!g_switch, -1);
+ retv_if(!g_switch->callback_hash, -1);
+ retv_if(!callback_key, -1);
+
+ if (callback) {
+ struct switch_callback_s *cb_item = NULL;
+ cb_item = g_try_new(struct switch_callback_s, 1);
+ retv_if(!cb_item, -1);
+
+ cb_item->callback = callback;
+ cb_item->cb_data = cb_data;
+
+ g_hash_table_insert(g_switch->callback_hash,
+ g_strdup(callback_key), cb_item);
+ } else {
+ g_hash_table_remove(g_switch->callback_hash, callback_key);
+ }
+
+ return 0;
+}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<manifest xmlns="http://tizen.org/ns/packages" api-version="5.0" package="@PROJECT_NAME@" version="1.0.0">
+<profile name="iot-headless"/>
+<service-application appid="@PROJECT_NAME@" auto-restart="true" exec="@PROJECT_NAME@" multiple="false" nodisplay="true" on-boot="true" taskmanage="false" type="capp">
+ <label>@PROJECT_NAME@</label>
+ <icon>@PROJECT_NAME@.png</icon>
+ <metadata key="http://tizen.org/iot/metadata/master" value="shared/res/master.json"/>
+ <metadata key="http://tizen.org/iot/metadata/resource" value="shared/res/resource.json"/>
+ <metadata key="samsung-experience-service-api-level" value="1"/>
+ <background-category value="background-network"/>
+ <background-category value="iot-communication"/>
+</service-application>
+ <privileges>
+ <privilege>http://tizen.org/privilege/camera</privilege>
+ <privilege>http://tizen.org/privilege/peripheralio</privilege>
+ <privilege>http://tizen.org/privilege/appmanager.launch</privilege>
+ <privilege>http://tizen.org/privilege/datasharing</privilege>
+ <privilege>http://tizen.org/privilege/internet</privilege>
+ <privilege>http://tizen.org/privilege/softap</privilege>
+ <appdefined-privilege>http://com.samsung.tizen.smartthings-thing/appdefined/smartthings-thing.master</appdefined-privilege>
+ <appdefined-privilege>http://com.samsung.tizen.smartthings-thing/appdefined/smartthings-thing.resource</appdefined-privilege>
+ </privileges>
+</manifest>
--- /dev/null
+cd dashboard
+
+sdb root on;
+sdb shell 'mount -o remount,rw /';
+
+sdb shell 'systemctl stop iot-dashboard'
+
+sdb shell 'rm -rf /opt/home/dashboard'
+sdb shell 'mkdir -p /opt/home/dashboard/public/js';
+sdb shell 'mkdir -p /opt/home/dashboard/public/css';
+
+sdb push server.js /opt/home/dashboard;
+sdb push default.gif /opt/home/dashboard;
+sdb push public/index.html /opt/home/dashboard/public/index.html;
+sdb push public/test.html /opt/home/dashboard/public/test.html;
+sdb push public/js/app.js /opt/home/dashboard/public/js/app.js;
+sdb push public/css/style.css /opt/home/dashboard/public/css/style.css;
+
+sdb shell 'cd /opt/home/dashboard; find .';
+
+# sdb shell 'cd /opt/home/dashboard; iotjs server.js'
+
+sdb shell 'systemctl start iot-dashboard'
+sdb shell 'systemctl status iot-dashboard'