From 99914a58a2d5b2638e2c1fdac5ca74a2d247e6fa Mon Sep 17 00:00:00 2001 From: Romain Forlot Date: Wed, 7 Nov 2018 10:54:01 +0100 Subject: First simple platform-info API implementation Bug-AGL: SPEC-1917 Change-Id: I300155302c9d69c6549ddabc6af53e2ad55eb18d Signed-off-by: Romain Forlot --- .gitignore | 8 + .gitmodules | 3 + CMakeLists.txt | 3 + LICENSE | 201 ++++++++++++++++++++ README.md | 47 +++++ app-afb-helpers-submodule | 1 + autobuild/agl/autobuild | 75 ++++++++ autobuild/linux/autobuild | 75 ++++++++ conf.d/cmake/config.cmake | 208 +++++++++++++++++++++ conf.d/packaging/deb/agl-service-platform-info.dsc | 18 ++ .../deb/debian.agl-service-platform-info.install | 1 + conf.d/packaging/deb/debian.changelog | 5 + conf.d/packaging/deb/debian.compat | 1 + conf.d/packaging/deb/debian.control | 19 ++ conf.d/packaging/deb/debian.rules | 14 ++ .../packaging/rpm/agl-service-platform-info.spec | 66 +++++++ conf.d/wgt/config.xml.in | 15 ++ htdocs/AFB-websock.js | 177 ++++++++++++++++++ htdocs/CMakeLists.txt | 33 ++++ htdocs/assets/background_iot_bzh_light.jpg | Bin 0 -> 40718 bytes htdocs/assets/favicon.ico | Bin 0 -> 1150 bytes htdocs/assets/iot-bzh-logo-small.png | Bin 0 -> 14449 bytes htdocs/index.html | 49 +++++ htdocs/iotbzh-Binding.css | 59 ++++++ htdocs/iotbzh-Binding.js | 104 +++++++++++ src/CMakeLists.txt | 33 ++++ src/platform-info-apidef.h | 64 +++++++ src/platform-info-apidef.json | 50 +++++ src/platform-info-binding.c | 125 +++++++++++++ src/platform-info-binding.h | 27 +++ test/CMakeLists.txt | 19 ++ test/aft-BasicAPITests.lua | 4 + test/aft-info.json | 23 +++ 33 files changed, 1527 insertions(+) create mode 100644 .gitignore create mode 100644 .gitmodules create mode 100644 CMakeLists.txt create mode 100644 LICENSE create mode 100644 README.md create mode 160000 app-afb-helpers-submodule create mode 100755 autobuild/agl/autobuild create mode 100755 autobuild/linux/autobuild create mode 100644 conf.d/cmake/config.cmake create mode 100644 conf.d/packaging/deb/agl-service-platform-info.dsc create mode 100644 conf.d/packaging/deb/debian.agl-service-platform-info.install create mode 100644 conf.d/packaging/deb/debian.changelog create mode 100644 conf.d/packaging/deb/debian.compat create mode 100644 conf.d/packaging/deb/debian.control create mode 100644 conf.d/packaging/deb/debian.rules create mode 100644 conf.d/packaging/rpm/agl-service-platform-info.spec create mode 100644 conf.d/wgt/config.xml.in create mode 100644 htdocs/AFB-websock.js create mode 100644 htdocs/CMakeLists.txt create mode 100644 htdocs/assets/background_iot_bzh_light.jpg create mode 100644 htdocs/assets/favicon.ico create mode 100644 htdocs/assets/iot-bzh-logo-small.png create mode 100644 htdocs/index.html create mode 100644 htdocs/iotbzh-Binding.css create mode 100644 htdocs/iotbzh-Binding.js create mode 100644 src/CMakeLists.txt create mode 100644 src/platform-info-apidef.h create mode 100644 src/platform-info-apidef.json create mode 100644 src/platform-info-binding.c create mode 100644 src/platform-info-binding.h create mode 100644 test/CMakeLists.txt create mode 100644 test/aft-BasicAPITests.lua create mode 100644 test/aft-info.json diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3354051 --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +build* +package +nbproject/private +.stfolder +.*.sw* +*.tar.gz +.vscode +__* diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..8f248e8 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "app-afb-helpers-submodule"] + path = app-afb-helpers-submodule + url = https://gerrit.automotivelinux.org/gerrit/p/apps/app-afb-helpers-submodule.git diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..c3650da --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,3 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 3.5) + +include(${CMAKE_CURRENT_SOURCE_DIR}/conf.d/cmake/config.cmake) diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..261eeb9 --- /dev/null +++ b/LICENSE @@ -0,0 +1,201 @@ + 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 [yyyy] [name of copyright owner] + + 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. diff --git a/README.md b/README.md new file mode 100644 index 0000000..1222e31 --- /dev/null +++ b/README.md @@ -0,0 +1,47 @@ +# agl-service-platform-info + +AF binding that reads system and platform information and expose them through +its API. The binding reads all files within /etc/platform-info directory and try +to serialize them as JSON. Then you could access to a JSON object using a +doted path. + +i.e: **build.machine.model** or **build.id** + +## Setup + +```bash +git clone --recursive https://github.com/iotbzh/agl-service-platform-info +cd agl-service-platform-info +#setup your build environement +. /xdt/sdk/environment-setup-aarch64-agl-linux +#build your application +./conf.d/autobuild/agl/autobuild package +``` + +## Build for 'native' Linux distros (Fedora, openSUSE, Debian, Ubuntu, ...) + +```bash +./conf.d/autobuild/linux/autobuild package +``` + +## Deploy + +### AGL + +```bash +export YOUR_BOARD_IP=192.168.1.X +export APP_NAME=agl-service-platform-info +scp build/${APP_NAME}.wgt root@${YOUR_BOARD_IP}:/tmp +ssh root@${YOUR_BOARD_IP} afm-util install /tmp/${APP_NAME}.wgt +APP_VERSION=$(ssh root@${YOUR_BOARD_IP} afm-util list | grep ${APP_NAME}@ | cut -d"\"" -f4| cut -d"@" -f2) +ssh root@${YOUR_BOARD_IP} afm-util start ${APP_NAME}@${APP_VERSION} +``` + +## Usage + +### Get verb + +```bash +afb-client-demo ws://localhost:1234/api?token= platform-info get ".build.layers.agl-manifest.revision" +{"response":"7383840-dirty","jtype":"afb-reply","request":{"status":"success","uuid":"3ab64378-44ac-45d1-ad1a-9db7c6c33545"}} +``` diff --git a/app-afb-helpers-submodule b/app-afb-helpers-submodule new file mode 160000 index 0000000..f0ce5b6 --- /dev/null +++ b/app-afb-helpers-submodule @@ -0,0 +1 @@ +Subproject commit f0ce5b665dd33b285d723720c16ac0542cde4e6e diff --git a/autobuild/agl/autobuild b/autobuild/agl/autobuild new file mode 100755 index 0000000..a832db4 --- /dev/null +++ b/autobuild/agl/autobuild @@ -0,0 +1,75 @@ +#!/usr/bin/make -f +# Copyright (C) 2015 - 2018 "IoT.bzh" +# Author "Romain Forlot" +# +# 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. + +THISFILE := $(lastword $(MAKEFILE_LIST)) +BUILD_DIR := $(abspath $(dir $(THISFILE))/../../build) +DEST := ${BUILD_DIR} + +.PHONY: all clean distclean configure build package help update + +all: help + +help: + @echo "List of targets available:" + @echo "" + @echo "- all" + @echo "- clean" + @echo "- distclean" + @echo "- configure" + @echo "- build: compilation, link and prepare files for package into a widget" + @echo "- package: output a widget file '*.wgt'" + @echo "- install: install in your ${CMAKE_INSTALL_DIR} directory" + @echo "" + @echo "Usage: ./autobuild/agl/autobuild package DEST=${HOME}/opt" + @echo "Don't use your build dir as DEST as wgt file is generated at this location" + +update: configure + @cmake --build ${BUILD_DIR} --target autobuild + +clean: + @([ -d ${BUILD_DIR} ] && make -C ${BUILD_DIR} ${CLEAN_ARGS} clean) || echo Nothing to clean + +distclean: + @rm -rf ${BUILD_DIR} + +configure: + @[ -d ${BUILD_DIR} ] || mkdir -p ${BUILD_DIR} + @[ -f ${BUILD_DIR}/Makefile ] || (cd ${BUILD_DIR} && cmake ${CONFIGURE_ARGS} ..) + +build: configure + @cmake --build ${BUILD_DIR} ${BUILD_ARGS} --target all + +package: build + @mkdir -p ${BUILD_DIR}/$@/bin + @mkdir -p ${BUILD_DIR}/$@/etc + @mkdir -p ${BUILD_DIR}/$@/lib + @mkdir -p ${BUILD_DIR}/$@/htdocs + @mkdir -p ${BUILD_DIR}/$@/var + @cmake --build ${BUILD_DIR} ${PACKAGE_ARGS} --target widget + @mkdir -p ${DEST} && cp ${BUILD_DIR}/*.wgt ${DEST} + +package-test: build + @mkdir -p ${BUILD_DIR}/$@/bin + @mkdir -p ${BUILD_DIR}/$@/etc + @mkdir -p ${BUILD_DIR}/$@/lib + @mkdir -p ${BUILD_DIR}/$@/htdocs + @mkdir -p ${BUILD_DIR}/$@/var + @cmake --build ${BUILD_DIR} ${PACKAGE_ARGS} --target widget + @cmake --build ${BUILD_DIR} ${PACKAGE_ARGS} --target test_widget + @mkdir -p ${DEST} && cp ${BUILD_DIR}/*.wgt ${DEST} + +install: build + @cmake --build ${BUILD_DIR} ${INSTALL_ARGS} --target install diff --git a/autobuild/linux/autobuild b/autobuild/linux/autobuild new file mode 100755 index 0000000..a832db4 --- /dev/null +++ b/autobuild/linux/autobuild @@ -0,0 +1,75 @@ +#!/usr/bin/make -f +# Copyright (C) 2015 - 2018 "IoT.bzh" +# Author "Romain Forlot" +# +# 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. + +THISFILE := $(lastword $(MAKEFILE_LIST)) +BUILD_DIR := $(abspath $(dir $(THISFILE))/../../build) +DEST := ${BUILD_DIR} + +.PHONY: all clean distclean configure build package help update + +all: help + +help: + @echo "List of targets available:" + @echo "" + @echo "- all" + @echo "- clean" + @echo "- distclean" + @echo "- configure" + @echo "- build: compilation, link and prepare files for package into a widget" + @echo "- package: output a widget file '*.wgt'" + @echo "- install: install in your ${CMAKE_INSTALL_DIR} directory" + @echo "" + @echo "Usage: ./autobuild/agl/autobuild package DEST=${HOME}/opt" + @echo "Don't use your build dir as DEST as wgt file is generated at this location" + +update: configure + @cmake --build ${BUILD_DIR} --target autobuild + +clean: + @([ -d ${BUILD_DIR} ] && make -C ${BUILD_DIR} ${CLEAN_ARGS} clean) || echo Nothing to clean + +distclean: + @rm -rf ${BUILD_DIR} + +configure: + @[ -d ${BUILD_DIR} ] || mkdir -p ${BUILD_DIR} + @[ -f ${BUILD_DIR}/Makefile ] || (cd ${BUILD_DIR} && cmake ${CONFIGURE_ARGS} ..) + +build: configure + @cmake --build ${BUILD_DIR} ${BUILD_ARGS} --target all + +package: build + @mkdir -p ${BUILD_DIR}/$@/bin + @mkdir -p ${BUILD_DIR}/$@/etc + @mkdir -p ${BUILD_DIR}/$@/lib + @mkdir -p ${BUILD_DIR}/$@/htdocs + @mkdir -p ${BUILD_DIR}/$@/var + @cmake --build ${BUILD_DIR} ${PACKAGE_ARGS} --target widget + @mkdir -p ${DEST} && cp ${BUILD_DIR}/*.wgt ${DEST} + +package-test: build + @mkdir -p ${BUILD_DIR}/$@/bin + @mkdir -p ${BUILD_DIR}/$@/etc + @mkdir -p ${BUILD_DIR}/$@/lib + @mkdir -p ${BUILD_DIR}/$@/htdocs + @mkdir -p ${BUILD_DIR}/$@/var + @cmake --build ${BUILD_DIR} ${PACKAGE_ARGS} --target widget + @cmake --build ${BUILD_DIR} ${PACKAGE_ARGS} --target test_widget + @mkdir -p ${DEST} && cp ${BUILD_DIR}/*.wgt ${DEST} + +install: build + @cmake --build ${BUILD_DIR} ${INSTALL_ARGS} --target install diff --git a/conf.d/cmake/config.cmake b/conf.d/cmake/config.cmake new file mode 100644 index 0000000..d57b4aa --- /dev/null +++ b/conf.d/cmake/config.cmake @@ -0,0 +1,208 @@ +########################################################################### +# Copyright 2015, 2016, 2018 IoT.bzh +# +# author: Fulup Ar Foll +# +# 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. +########################################################################### + +# Project Info +# ------------------ +set(PROJECT_NAME "Platform-info_binding") +set(PROJECT_VERSION 6.90) +set(API_NAME platform-info) +set(PROJECT_PRETTY_NAME "Platform Information provider binding") +set(PROJECT_DESCRIPTION "A binding meant to provide system, platform, build information for others bindings and apps") +set(PROJECT_URL "https://github.com/iotbzh/agl-service-platform-info") +set(PROJECT_ICON "icon.png") +set(PROJECT_AUTHOR "Forlot, Romain") +set(PROJECT_AUTHOR_MAIL "romain.forlot@iot.bzh") +set(PROJECT_LICENSE "APL2.0") +set(PROJECT_LANGUAGES "C") + +# Which directories inspect to find CMakeLists.txt target files +# set(PROJECT_SRC_DIR_PATTERN "*") + +# Where are stored the project configuration files +# relative to the root project directory +set(PROJECT_CMAKE_CONF_DIR "conf.d") + +# Compilation Mode (DEBUG, RELEASE, COVERAGE or PROFILING) +# ---------------------------------- +#set(BUILD_TYPE "DEBUG") +#set(USE_EFENCE 1) + +# Kernel selection if needed. You can choose between a +# mandatory version to impose a minimal version. +# Or check Kernel minimal version and just print a Warning +# about missing features and define a preprocessor variable +# to be used as preprocessor condition in code to disable +# incompatibles features. Preprocessor define is named +# KERNEL_MINIMAL_VERSION_OK. +# +# NOTE*** FOR NOW IT CHECKS KERNEL Yocto environment and +# Yocto SDK Kernel version. +# ----------------------------------------------- +#set (kernel_mandatory_version 4.8) +#set (kernel_minimal_version 4.8) + +# Compiler selection if needed. Impose a minimal version. +# ----------------------------------------------- +set (gcc_minimal_version 4.9) + +# PKG_CONFIG required packages +# ----------------------------- +set (PKG_REQUIRED_LIST + json-c>=0.12 + afb-daemon +) + +# You can also consider to include libsystemd +# ----------------------------------- +#list (APPEND PKG_REQUIRED_LIST libsystemd>=222) + +# Prefix path where will be installed the files +# Default: /usr/local (need root permission to write in) +# ------------------------------------------------------ +#set(INSTALL_PREFIX /opt/AGL CACHE PATH "INSTALL PREFIX PATH") + +# Customize link option +# ----------------------------- +#list(APPEND link_libraries -an-option) + +# Compilation options definition +# Use CMake generator expressions to specify only for a specific language +# Values are prefilled with default options that is currently used. +# Either separate options with ";", or each options must be quoted separately +# DO NOT PUT ALL OPTION QUOTED AT ONCE , COMPILATION COULD FAILED ! +# ---------------------------------------------------------------------------- +#set(COMPILE_OPTIONS +# -Wall +# -Wextra +# -Wconversion +# -Wno-unused-parameter +# -Wno-sign-compare +# -Wno-sign-conversion +# -Werror=maybe-uninitialized +# -Werror=implicit-function-declaration +# -ffunction-sections +# -fdata-sections +# -fPIC +# CACHE STRING "Compilation flags") +#set(C_COMPILE_OPTIONS "" CACHE STRING "Compilation flags for C language.") +#set(CXX_COMPILE_OPTIONS "" CACHE STRING "Compilation flags for C++ language.") +#set(PROFILING_COMPILE_OPTIONS +# -g +# -O0 +# -pg +# -Wp,-U_FORTIFY_SOURCE +# CACHE STRING "Compilation flags for PROFILING build type.") +#set(DEBUG_COMPILE_OPTIONS +# -g +# -ggdb +# CACHE STRING "Compilation flags for DEBUG build type.") +#set(COVERAGE_COMPILE_OPTIONS +# -g +# -O0 +# --coverage +# CACHE STRING "Compilation flags for COVERAGE build type.") +#set(RELEASE_COMPILE_OPTIONS +# -O2 +# -pipe +# -D_FORTIFY_SOURCE=2 +# -fstack-protector-strong +# -Wformat -Wformat-security +# -Werror=format-security +# -feliminate-unused-debug-types +# -Wl,-O1 +# -Wl,--hash-style=gnu +# -Wl,--as-needed +# -fstack-protector-strong +# -Wl,-z,relro,-z,now +# CACHE STRING "Compilation flags for RELEASE build type.") + +add_definitions(-DAFB_BINDING_VERSION=3) + +# Location for config.xml.in template file. +# +# If you keep them commented then it will build with a default minimal widget +# template which is very simple and it is highly probable that it will not suit +# to your app. +# ----------------------------------------- +#set(WIDGET_ICON "conf.d/wgt/${PROJECT_ICON}" CACHE PATH "Path to the widget icon") +#set(WIDGET_CONFIG_TEMPLATE "${CMAKE_CURRENT_SOURCE_DIR}/conf.d/wgt/config.xml.in" CACHE PATH "Path to widget config file template (config.xml.in)") +#set(TEST_WIDGET_CONFIG_TEMPLATE "${CMAKE_CURRENT_SOURCE_DIR}/conf.d/wgt/test-config.xml.in" CACHE PATH "Path to the test widget config file template (test-config.xml.in)") + +# Mandatory widget Mimetype specification of the main unit +# -------------------------------------------------------------------------- +# Choose between : +#- text/html : HTML application, +# content.src designates the home page of the application +# +#- application/vnd.agl.native : AGL compatible native, +# content.src designates the relative path of the binary. +# +# - application/vnd.agl.service: AGL service, content.src is not used. +# +#- ***application/x-executable***: Native application, +# content.src designates the relative path of the binary. +# For such application, only security setup is made. +# +set(WIDGET_TYPE application/vnd.agl.service) + +# Mandatory Widget entry point file of the main unit +# -------------------------------------------------------------- +# This is the file that will be executed, loaded, +# at launch time by the application framework. +# +set(WIDGET_ENTRY_POINT "lib/afb-platform-info.so") + +# Optional dependencies order +# --------------------------- +#set(EXTRA_DEPENDENCIES_ORDER) + +# Optional Extra global include path +# ----------------------------------- +#set(EXTRA_INCLUDE_DIRS) + +# Optional extra libraries +# ------------------------- +#set(EXTRA_LINK_LIBRARIES) + +# Optional force binding Linking flag +# ------------------------------------ +# set(BINDINGS_LINK_FLAG LinkOptions ) + +# Optional force package prefix generation, like widget +# ----------------------------------------------------- +# set(PKG_PREFIX DestinationPath) + +# Optional Application Framework security token +# and port use for remote debugging. +#------------------------------------------------------------ +set(AFB_TOKEN "" CACHE PATH "Default binder security token") +set(AFB_REMPORT "1234" CACHE PATH "Default binder listening port") + +# Print a helper message when every thing is finished +# ---------------------------------------------------- +set(CLOSING_MESSAGE "Typical binding launch: cd ${CMAKE_BINARY_DIR}/package \\&\\& afb-daemon --port=${AFB_REMPORT} --workdir=. --ldpaths=lib --roothttp=htdocs --token=\"${AFB_TOKEN}\" --tracereq=common --verbose") +set(PACKAGE_MESSAGE "Install widget file using in the target : afm-util install ${PROJECT_NAME}.wgt") + +# Optional schema validator about now only XML, LUA and JSON +# are supported +#------------------------------------------------------------ +#set(LUA_CHECKER "luac" "-p" CACHE STRING "LUA compiler") +#set(XML_CHECKER "xmllint" CACHE STRING "XML linter") +#set(JSON_CHECKER "json_verify" CACHE STRING "JSON linter") + +include(CMakeAfbTemplates) diff --git a/conf.d/packaging/deb/agl-service-platform-info.dsc b/conf.d/packaging/deb/agl-service-platform-info.dsc new file mode 100644 index 0000000..0c603de --- /dev/null +++ b/conf.d/packaging/deb/agl-service-platform-info.dsc @@ -0,0 +1,18 @@ +Format: 1.0 +Source: agl-service-os-info +Binary: agl-service-os-info-bin +Architecture: any +Version: 2.0-0 +Maintainer: Iot-Team +Standards-Version: 3.8.2 +Homepage: https://github.com/iotbzh/agl-service-os-info +Build-Depends: debhelper (>= 5), + pkg-config, + cmake, + gcc, + g++, + libjson-c-dev , + libsystemd-dev (>= 222), + agl-app-framework-binder-dev , + agl-libmicrohttpd-dev (>= 0.9.55) +Debtransform-Tar: agl-service-os-info_1.0.orig.tar.gz diff --git a/conf.d/packaging/deb/debian.agl-service-platform-info.install b/conf.d/packaging/deb/debian.agl-service-platform-info.install new file mode 100644 index 0000000..6399692 --- /dev/null +++ b/conf.d/packaging/deb/debian.agl-service-platform-info.install @@ -0,0 +1 @@ +/opt/AGL/* diff --git a/conf.d/packaging/deb/debian.changelog b/conf.d/packaging/deb/debian.changelog new file mode 100644 index 0000000..de0a835 --- /dev/null +++ b/conf.d/packaging/deb/debian.changelog @@ -0,0 +1,5 @@ +agl-service-os-info (1.0-0) UNRELEASED; urgency=low + + * init build + + -- Iot-Team Wed, 7 Nov 2018 10:50:38 +0100 diff --git a/conf.d/packaging/deb/debian.compat b/conf.d/packaging/deb/debian.compat new file mode 100644 index 0000000..ec63514 --- /dev/null +++ b/conf.d/packaging/deb/debian.compat @@ -0,0 +1 @@ +9 diff --git a/conf.d/packaging/deb/debian.control b/conf.d/packaging/deb/debian.control new file mode 100644 index 0000000..4eb8b99 --- /dev/null +++ b/conf.d/packaging/deb/debian.control @@ -0,0 +1,19 @@ +Priority: optional +Maintainer: Iot-Team +Source: agl-service-os-info +Build-Depends: debhelper (>= 5), + pkg-config, + cmake, + gcc, + g++, + libjson-c-dev , + libsystemd-dev (>= 222), + agl-app-framework-binder-dev , + agl-libmicrohttpd-dev (>= 0.9.55) +Standards-Version: 3.8.2 +Homepage: https://github.com/iotbzh/agl-service-os-info + +Package: agl-service-os-info +Section: libs +Architecture: any +Description: Provide an AGL OS information Binding diff --git a/conf.d/packaging/deb/debian.rules b/conf.d/packaging/deb/debian.rules new file mode 100644 index 0000000..5bc5fc2 --- /dev/null +++ b/conf.d/packaging/deb/debian.rules @@ -0,0 +1,14 @@ +#!/usr/bin/make -f +# -*- makefile -*- +# Uncomment this to turn on verbose mode. +#export DH_VERBOSE=1 + +%: + bash /etc/profile.d/AGL-app-framework-binder.sh + dh $@ + +override_dh_auto_configure: + dh_auto_configure -- -DCMAKE_INSTALL_PREFIX=/opt/AGL/afm/applications/ + +override_dh_auto_install: + dh_auto_install --destdir=/usr/src/packages/BUILD/debian/tmp diff --git a/conf.d/packaging/rpm/agl-service-platform-info.spec b/conf.d/packaging/rpm/agl-service-platform-info.spec new file mode 100644 index 0000000..d495571 --- /dev/null +++ b/conf.d/packaging/rpm/agl-service-platform-info.spec @@ -0,0 +1,66 @@ +########################################################################### +# Copyright 2015, 2016, 2017 IoT.bzh +# +# author: Iot-Team +# +# 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. +########################################################################### + + +Name: agl-helloworld-service +Version: 1.0 +Release: 1 +Group: AGL +License: APL2.0 +Summary: Provide an AGL Helloworld Binding +Url: https://github.com/iotbzh/helloworld-service +Source0: %{name}_%{version}.orig.tar.gz + +BuildRequires: cmake +BuildRequires: gcc gcc-c++ +BuildRequires: pkgconfig(json-c) +BuildRequires: pkgconfig(libsystemd) >= 222 +BuildRequires: pkgconfig(afb-daemon) +BuildRequires: pkgconfig(libmicrohttpd) >= 0.9.55 + + +BuildRoot: %{_tmppath}/%{name}-%{version}-build + +%define _prefix /opt/AGL/helloworld-service +%define __cmake cmake + +%description +Provide an AGL Helloworld Binding + +%prep +%setup -q + +%build +%cmake -DCMAKE_INSTALL_PREFIX:PATH=%{_libdir} +make %{?_smp_mflags} + +%install +CURDIR=$(pwd) +[ -d build ] && cd build +make populate +mkdir -p %{?buildroot}%{_prefix} +cp -r package/* %{?buildroot}%{_prefix} + +cd $CURDIR +find %{?buildroot}%{_prefix} -type d -exec echo "%dir {}" \;>> pkg_file +find %{?buildroot}%{_prefix} -type f -exec echo "{}" \;>> pkg_file +sed -i 's@%{?buildroot}@@g' pkg_file + + +%files -f pkg_file +%defattr(-,root,root) diff --git a/conf.d/wgt/config.xml.in b/conf.d/wgt/config.xml.in new file mode 100644 index 0000000..9cd3c30 --- /dev/null +++ b/conf.d/wgt/config.xml.in @@ -0,0 +1,15 @@ + + + @PROJECT_NAME@ + + + @PROJECT_DESCRIPTION@ + @PROJECT_AUTHOR@ <@PROJECT_AUTHOR_MAIL@> + @PROJECT_LICENSE@ + + + + + + + diff --git a/htdocs/AFB-websock.js b/htdocs/AFB-websock.js new file mode 100644 index 0000000..99ab3b8 --- /dev/null +++ b/htdocs/AFB-websock.js @@ -0,0 +1,177 @@ +var urlws; +var urlhttp; + +AFB = function(base, initialtoken){ + +urlws = "ws://"+window.location.host+"/"+base; +urlhttp = "http://"+window.location.host+"/"+base; + +/*********************************************/ +/**** ****/ +/**** AFB_context ****/ +/**** ****/ +/*********************************************/ +var AFB_context; +{ + var UUID = undefined; + var TOKEN = initialtoken; + + var context = function(token, uuid) { + this.token = token; + this.uuid = uuid; + } + + context.prototype = { + get token() {return TOKEN;}, + set token(tok) {if(tok) TOKEN=tok;}, + get uuid() {return UUID;}, + set uuid(id) {if(id) UUID=id;} + }; + + AFB_context = new context(); +} +/*********************************************/ +/**** ****/ +/**** AFB_websocket ****/ +/**** ****/ +/*********************************************/ +var AFB_websocket; +{ + var CALL = 2; + var RETOK = 3; + var RETERR = 4; + var EVENT = 5; + + var PROTO1 = "x-afb-ws-json1"; + + AFB_websocket = function(onopen, onabort) { + var u = urlws; + if (AFB_context.token) { + u = u + '?x-afb-token=' + AFB_context.token; + if (AFB_context.uuid) + u = u + '&x-afb-uuid=' + AFB_context.uuid; + } + this.ws = new WebSocket(u, [ PROTO1 ]); + this.pendings = {}; + this.awaitens = {}; + this.counter = 0; + this.ws.onopen = onopen.bind(this); + this.ws.onerror = onerror.bind(this); + this.ws.onclose = onclose.bind(this); + this.ws.onmessage = onmessage.bind(this); + this.onopen = onopen; + this.onabort = onabort; + this.onclose = onabort; + } + + function onerror(event) { + var f = this.onabort; + if (f) { + delete this.onopen; + delete this.onabort; + f && f(this); + } + this.onerror && this.onerror(this); + } + + function onopen(event) { + var f = this.onopen; + delete this.onopen; + delete this.onabort; + f && f(this); + } + + function onclose(event) { + for (var id in this.pendings) { + var ferr = this.pendings[id].onerror; + ferr && ferr(null, this); + } + this.pendings = {}; + this.onclose && this.onclose(); + } + + function fire(awaitens, name, data) { + var a = awaitens[name]; + if (a) + a.forEach(function(handler){handler(data);}); + var i = name.indexOf("/"); + if (i >= 0) { + a = awaitens[name.substring(0,i)]; + if (a) + a.forEach(function(handler){handler(data);}); + } + a = awaitens["*"]; + if (a) + a.forEach(function(handler){handler(data);}); + } + + function reply(pendings, id, ans, offset) { + if (id in pendings) { + var p = pendings[id]; + delete pendings[id]; + var f = p[offset]; + f(ans); + } + } + + function onmessage(event) { + var obj = JSON.parse(event.data); + var code = obj[0]; + var id = obj[1]; + var ans = obj[2]; + AFB_context.token = obj[3]; + switch (code) { + case RETOK: + reply(this.pendings, id, ans, 0); + break; + case RETERR: + reply(this.pendings, id, ans, 1); + break; + case EVENT: + default: + fire(this.awaitens, id, ans); + break; + } + } + + function close() { + this.ws.close(); + this.onabort(); + } + + function call(method, request) { + return new Promise((function(resolve, reject){ + var id, arr; + do { + id = String(this.counter = 4095 & (this.counter + 1)); + } while (id in this.pendings); + this.pendings[id] = [ resolve, reject ]; + arr = [CALL, id, method, request ]; + if (AFB_context.token) arr.push(AFB_context.token); + this.ws.send(JSON.stringify(arr)); + }).bind(this)); + } + + function onevent(name, handler) { + var id = name; + var list = this.awaitens[id] || (this.awaitens[id] = []); + list.push(handler); + } + + AFB_websocket.prototype = { + close: close, + call: call, + onevent: onevent + }; +} +/*********************************************/ +/**** ****/ +/**** ****/ +/**** ****/ +/*********************************************/ +return { + context: AFB_context, + ws: AFB_websocket +}; +}; + diff --git a/htdocs/CMakeLists.txt b/htdocs/CMakeLists.txt new file mode 100644 index 0000000..7aa0ce1 --- /dev/null +++ b/htdocs/CMakeLists.txt @@ -0,0 +1,33 @@ +########################################################################### +# Copyright 2015, 2016, 2017 IoT.bzh +# +# author: Fulup Ar Foll +# +# 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. +########################################################################### + + + +################################################## +# HTML Testing Files +################################################## +PROJECT_TARGET_ADD(htdocs) + + file(GLOB SOURCE_FILES "*.html" "*.js" "*.jpg" "*.css" "assets") + + add_input_files("${SOURCE_FILES}") + + SET_TARGET_PROPERTIES(${TARGET_NAME} PROPERTIES + LABELS "HTDOCS" + OUTPUT_NAME ${TARGET_NAME} + ) diff --git a/htdocs/assets/background_iot_bzh_light.jpg b/htdocs/assets/background_iot_bzh_light.jpg new file mode 100644 index 0000000..f47d2ee Binary files /dev/null and b/htdocs/assets/background_iot_bzh_light.jpg differ diff --git a/htdocs/assets/favicon.ico b/htdocs/assets/favicon.ico new file mode 100644 index 0000000..eeb7ab7 Binary files /dev/null and b/htdocs/assets/favicon.ico differ diff --git a/htdocs/assets/iot-bzh-logo-small.png b/htdocs/assets/iot-bzh-logo-small.png new file mode 100644 index 0000000..2c3b2ae Binary files /dev/null and b/htdocs/assets/iot-bzh-logo-small.png differ diff --git a/htdocs/index.html b/htdocs/index.html new file mode 100644 index 0000000..ffefe20 --- /dev/null +++ b/htdocs/index.html @@ -0,0 +1,49 @@ + + + + Simple Helloworld binding Test + + + + + + + + + + +

Simple Helloworld binding Test

+ + + + +

+ +
+ + + + + + + + + +
+ +
+ + + diff --git a/htdocs/iotbzh-Binding.css b/htdocs/iotbzh-Binding.css new file mode 100644 index 0000000..96a04cc --- /dev/null +++ b/htdocs/iotbzh-Binding.css @@ -0,0 +1,59 @@ +body.page-content { + height: 100%; + width: auto; + margin-top: 20px; + background: url("assets/background_iot_bzh_light.jpg") 0 0 no-repeat; + background-size: cover; + background-position: center; +} + +img { + float: right; +} + +#question, +#output, +#outevt { + white-space: pre-wrap; +} + +button { + margin-right: 10px; + padding: 6px 8px; + font-size: large; +} + +pre { + outline: 1px solid #ccc; + padding: 5px; + margin: 5px; + background-color: white; + opacity: 0.85; + min-height: 5pc; + max-height: 10pc; + overflow: auto; +} + +pre#output { + max-height: 30pc; +} + +.string { + color: green; +} + +.number { + color: darkorange; +} + +.boolean { + color: blue; +} + +.null { + color: magenta; +} + +.key { + color: red; +} diff --git a/htdocs/iotbzh-Binding.js b/htdocs/iotbzh-Binding.js new file mode 100644 index 0000000..d2d870c --- /dev/null +++ b/htdocs/iotbzh-Binding.js @@ -0,0 +1,104 @@ +var afb = new AFB("api", "mysecret"); +var ws; +var evtidx = 0; +var count = 0; + + +//********************************************** +// Logger +//********************************************** +var log = { + command: function (api, verb, query) { + console.log("subscribe api=" + api + " verb=" + verb + " query=", query); + var question = urlws + "/" + api + "/" + verb + "?query=" + JSON.stringify(query); + log._write("question", count + ": " + log.syntaxHighlight(question)); + }, + + event: function (obj) { + console.log("gotevent:" + JSON.stringify(obj)); + log._write("outevt", (evtidx++) + ": " + JSON.stringify(obj)); + }, + + reply: function (obj) { + console.log("replyok:" + JSON.stringify(obj)); + log._write("output", count + ": OK: " + log.syntaxHighlight(obj)); + }, + + error: function (obj) { + console.log("replyerr:" + JSON.stringify(obj)); + log._write("output", count + ": ERROR: " + log.syntaxHighlight(obj)); + }, + + _write: function (element, msg) { + var el = document.getElementById(element); + el.innerHTML += msg + '\n'; + + // auto scroll down + setTimeout(function () { + el.scrollTop = el.scrollHeight; + }, 100); + }, + + syntaxHighlight: function (json) { + if (typeof json !== 'string') { + json = JSON.stringify(json, undefined, 2); + } + json = json.replace(/&/g, '&').replace(//g, '>'); + return json.replace(/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g, function (match) { + var cls = 'number'; + if (/^"/.test(match)) { + if (/:$/.test(match)) { + cls = 'key'; + } else { + cls = 'string'; + } + } else if (/true|false/.test(match)) { + cls = 'boolean'; + } else if (/null/.test(match)) { + cls = 'null'; + } + return '' + match + ''; + }); + }, +}; + +//********************************************** +// Generic function to call binder +//*********************************************** +function callbinder(api, verb, query) { + log.command(api, verb, query); + + // ws.call return a Promise + return ws.call(api + "/" + verb, query) + .then(function (res) { + log.reply(res); + count++; + return res; + }) + .catch(function (err) { + log.reply(err); + count++; + throw err; + }); +} + +//********************************************** +// Init - establish Websocket connection +//********************************************** +function init(elemid, api, verb, query) { + + function onopen() { + document.getElementById("main").style.visibility = "visible"; + document.getElementById("connected").innerHTML = "Binder WS Active"; + document.getElementById("connected").style.background = "lightgreen"; + ws.onevent("*", log.event); + } + + function onabort() { + document.getElementById("main").style.visibility = "hidden"; + document.getElementById("connected").innerHTML = "Connected Closed"; + document.getElementById("connected").style.background = "red"; + } + + ws = new afb.ws(onopen, onabort); +} diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 0000000..afa714f --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,33 @@ +########################################################################### +# Copyright 2015, 2016, 2017 IoT.bzh +# +# 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. +########################################################################### + +# Add target to project dependency list +PROJECT_TARGET_ADD(platform-info) + + # Define project Targets + ADD_LIBRARY(${TARGET_NAME} MODULE platform-info-binding.c) + + # Binder exposes a unique public entry point + SET_TARGET_PROPERTIES(${TARGET_NAME} PROPERTIES + PREFIX "afb-" + LABELS "BINDING" + OUTPUT_NAME ${TARGET_NAME} + ) + + TARGET_LINK_LIBRARIES(${TARGET_NAME} + afb-helpers + ${link_libraries} + ) diff --git a/src/platform-info-apidef.h b/src/platform-info-apidef.h new file mode 100644 index 0000000..c09da63 --- /dev/null +++ b/src/platform-info-apidef.h @@ -0,0 +1,64 @@ +static const struct afb_auth _afb_auths_platform_info[] = { + { .type = afb_auth_Permission, .text = "urn:AGL:permission::platform:info:get " }, + { .type = afb_auth_Permission, .text = "urn:AGL:permission::platform:info:set " } +}; + + void afv_get(afb_req_t req); + void afv_set(afb_req_t req); + void afv_subscribe(afb_req_t req); + void afv_unsubscribe(afb_req_t req); + +static const struct afb_verb_v3 _afb_verbs_platform_info[] = { + { + .verb = "get", + .callback = afv_get, + .auth = &_afb_auths_platform_info[0], + .info = "Get a platform data.", + .session = AFB_SESSION_NONE + }, + { + .verb = "set", + .callback = afv_set, + .auth = &_afb_auths_platform_info[1], + .info = "Set a platform data.", + .session = AFB_SESSION_NONE + }, + { + .verb = "unsubscribe", + .callback = afv_unsubscribe, + .auth = NULL, + .info = "Unsubscribe to changes (hotplug event, failures, ...)", + .session = AFB_SESSION_NONE + }, + { + .verb = "subscribe", + .callback = afv_subscribe, + .auth = NULL, + .info = "Subscribe to changes (hotplug event, failures, ...)", + .session = AFB_SESSION_NONE + }, + { + .verb = NULL, + .callback = NULL, + .auth = NULL, + .info = NULL, + .session = 0 + } +}; + +int init(afb_api_t api); + +const struct afb_binding_v3 afbBindingV3 = { + .api = "platform-info", + .specification = NULL, + .info = "", + .verbs = _afb_verbs_platform_info, + .preinit = NULL, + .init = init, + .onevent = NULL, + .userdata = NULL, + .provide_class = NULL, + .require_class = NULL, + .require_api = NULL, + .noconcurrency = 0 +}; diff --git a/src/platform-info-apidef.json b/src/platform-info-apidef.json new file mode 100644 index 0000000..fb4b863 --- /dev/null +++ b/src/platform-info-apidef.json @@ -0,0 +1,50 @@ +{ + "afbidl": "0.0", + "info": { + "description": "Provide platform information to other bindings", + "title": "agl-service-platform-info", + "version": "1.0" + }, + "c-generator": { + "version": 3, + "prefix": "afv_", + "postfix": "", + "preinit": null, + "init": "init", + "onevent": null, + "scope": "static", + "private": true + }, + "api": { + "name": "platform-info", + "verbs": { + "get": { + "description": "Get a platform data.", + "permissions": { "session": "check" }, + "request": { "$ref": "#/schemas/get-request" }, + "reply": { "$ref": "#/schemas/any" } + }, + "subscribe": { + "description": "Subscribe to changes (hotplug event, failures, ...)" + }, + "unsubscribe": { + "description": "Unsubscribe to changes (hotplug event, failures, ...)" + } + } + }, + "schemas": { + "any": { + "title": "Any value", + "type": [ "null", "boolean", "object", "array", "number", "string" ] + }, + "get-request": { + "type": "object", + "properties": { + "oneOf": [ + { "type": "string"}, + { "type": "array", "items": { "type": "string"} } + ] + } + } + } +} diff --git a/src/platform-info-binding.c b/src/platform-info-binding.c new file mode 100644 index 0000000..c6bc9fd --- /dev/null +++ b/src/platform-info-binding.c @@ -0,0 +1,125 @@ +/* + * Copyright (C) 2016, 2018 "IoT.bzh" + * + * Author "Romain Forlot" + * + * 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. + */ + +#define _GNU_SOURCE +#include +#include +#include + +#include +#include "platform-info-binding.h" + +#ifndef PLATFORM_INFO_DIR +#define PLATFORM_INFO_DIR "/etc/platform-info" +#endif + +#ifndef HOTPLUG_NS +#define HOTPLUG_NS "hotplug" +#endif + +void afv_get(afb_req_t req) { + char *json_path = NULL, *full_json_path = NULL; + json_object *platform_info = (json_object*) afb_api_get_userdata(req->api); + json_object *args = afb_req_json(req), *result = NULL; + + switch (json_object_get_type(args)) { + case json_type_null: + result = platform_info; + break; + case json_type_string: + full_json_path = strdupa(json_object_get_string(args)); + result = platform_info; + for(json_path = strtok(full_json_path, "."); json_path && *json_path; json_path = strtok(NULL, ".")) { + if(! json_object_object_get_ex(result, json_path, &result)) { + afb_req_fail(req, "A key hasn't been found in JSON path.", json_path); + return; + } + } + break; + default: + afb_req_fail(req, "Type error", "Argument type is unknown, you must provide a string only"); + return; + } + + afb_req_success(req, result, NULL); +} + +void afv_set(afb_req_t req) { + json_object *platform_info = (json_object*) afb_api_get_userdata(req->api); + json_object *args = afb_req_json(req); + +#if (JSON_C_VERSION_MAJOR_VERSION == 0 && JSON_C_VERSION_MINOR_VERSION >= 13) + if(json_object_object_add(platform_info, HOTPLUG_NS, args)) { + afb_req_fail(req, "Addition fails", NULL); + return; + } +#else + json_object_object_add(platform_info, HOTPLUG_NS, args); +#endif + + afb_req_success(req, NULL, NULL); +} + +// TODO RFOR: interface with inotify and udev +void afv_unsubscribe(afb_req_t req) { + afb_req_success(req, NULL, NULL); +} + +void afv_subscribe(afb_req_t req) { + afb_req_success(req, NULL, NULL); +} + +int init(afb_api_t api) { + struct dirent* dir_ent = NULL; + DIR* dir_handle = opendir(PLATFORM_INFO_DIR); + json_object *json_file = json_object_new_object(), *current_file = NULL; + + while( (dir_ent = readdir(dir_handle)) != NULL) { + if(dir_ent->d_type == DT_REG && dir_ent->d_name[0] != '.') { + size_t filepath_len = strlen(PLATFORM_INFO_DIR) + strlen(dir_ent->d_name) + 2; + char *filepath = alloca(filepath_len); + + filepath = strncpy(filepath, PLATFORM_INFO_DIR, filepath_len); + filepath = strncat(filepath, "/", filepath_len - strlen(filepath) - 1); + filepath = strncat(filepath, dir_ent->d_name, filepath_len - strlen(filepath) - 1); + + AFB_DEBUG("File in processing: %s", filepath); + current_file = json_object_from_file(filepath); +#if (JSON_C_VERSION_MAJOR_VERSION == 0 && JSON_C_VERSION_MINOR_VERSION >= 13) + const char *error = NULL; + if( (error = json_util_get_last_err()) ) { + AFB_NOTICE("This file '%s' isn't a JSON file or have error: %s. len: %ld", filepath, error, filepath_len); + continue; + } +#else + if( current_file == NULL ) { + AFB_NOTICE("This file '%s' isn't a JSON file or have error.", filepath); + continue; + } +#endif + wrap_json_object_add(json_file, current_file); + AFB_DEBUG("JSON loaded: %s", json_object_get_string(json_file)); + } + } + + // Initializing the platform_info binding object and associated it to + // the api + afb_api_set_userdata(api, (void*)json_file); + + return 0; +} diff --git a/src/platform-info-binding.h b/src/platform-info-binding.h new file mode 100644 index 0000000..183fa86 --- /dev/null +++ b/src/platform-info-binding.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2016, 2018 "IoT.bzh" + * + * Author "Romain Forlot" + * + * 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 +#include "platform-info-apidef.h" + +struct key_search_t { + afb_api_t api; + json_object **result; +}; + +json_object *platform_info; diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt new file mode 100644 index 0000000..685ce9c --- /dev/null +++ b/test/CMakeLists.txt @@ -0,0 +1,19 @@ +PROJECT_TARGET_ADD(test-files) + + file(GLOB LUA_FILES "*.lua") + add_input_files("${LUA_FILES}") + + SET_TARGET_PROPERTIES(${TARGET_NAME} PROPERTIES + LABELS "TEST-DATA" + OUTPUT_NAME ${TARGET_NAME} + ) + +PROJECT_TARGET_ADD(test-configuration) + + file(GLOB CFG_FILES "*.json") + add_input_files("${CFG_FILES}") + + SET_TARGET_PROPERTIES(${TARGET_NAME} PROPERTIES + LABELS "TEST-CONFIG" + OUTPUT_NAME ${TARGET_NAME} + ) diff --git a/test/aft-BasicAPITests.lua b/test/aft-BasicAPITests.lua new file mode 100644 index 0000000..2806363 --- /dev/null +++ b/test/aft-BasicAPITests.lua @@ -0,0 +1,4 @@ +_AFT.testVerbStatusSuccess("Ping_verb_test", "helloworld", "ping", {}) +_AFT.testVerbStatusSuccess("TestArgs_verb_test", "helloworld", "testargs", { cezam = "open" }) +_AFT.testVerbStatusError("TestArgs_value_error_verb_test", "helloworld", "testargs", { cezam = "close" }) +_AFT.testVerbStatusError("TestArgs_key_error_verb_test", "helloworld", "testargs", { abracadabdra = "open" }) diff --git a/test/aft-info.json b/test/aft-info.json new file mode 100644 index 0000000..17251be --- /dev/null +++ b/test/aft-info.json @@ -0,0 +1,23 @@ +{ + "id": "http://iot.bzh/download/public/schema/json/ctl-schema.json#", + "$schema": "http://iot.bzh/download/public/schema/json/ctl-schema.json#", + "metadata": { + "uid": "OS Info binding Test", + "version": "1.0", + "api": "aft-os-info", + "info": "AFB-test binding configuration file to test os-info api.", + "require": [ + "os-info" + ] + }, + "testVerb": { + "uid": "short", + "info": "Launch the basic API tests", + "action": "lua://AFT#_launch_test", + "args": { + "trace": "os-info", + "files": "aft-BasicAPITests.lua" + } + } +} + -- cgit 1.2.3-korg