From fa46d3cd2c0166d064a720bd5e621b11751a9977 Mon Sep 17 00:00:00 2001 From: Tobias Jahnke Date: Fri, 9 Aug 2019 14:12:09 +0200 Subject: unicens-controller: insert initial code of service Bug-AGL: SPEC-2738 - adds service widget to control microphone mode, amplifier and slimamp master volume Signed-off-by: Tobias Jahnke Change-Id: I2463b0351c740c738e35185997d926a602bb2489 Signed-off-by: Tobias Jahnke --- .gitignore | 4 + CMakeLists.txt | 19 +++ README.md | 134 +++++++++++++++++++++ autobuild/agl/autobuild | 79 +++++++++++++ autobuild/linux/autobuild | 79 +++++++++++++ binding/CMakeLists.txt | 48 ++++++++ binding/amplifier/CMakeLists.txt | 32 +++++ binding/amplifier/amplifier.c | 124 ++++++++++++++++++++ binding/amplifier/amplifier.h | 27 +++++ binding/binding.c | 81 +++++++++++++ binding/microphone/CMakeLists.txt | 32 +++++ binding/microphone/microphone.c | 153 ++++++++++++++++++++++++ binding/microphone/microphone.h | 26 ++++ binding/slimamp/CMakeLists.txt | 32 +++++ binding/slimamp/slimamp.c | 110 +++++++++++++++++ binding/slimamp/slimamp.h | 21 ++++ binding/wrap-unicens/CMakeLists.txt | 27 +++++ binding/wrap-unicens/wrap-unicens.c | 228 ++++++++++++++++++++++++++++++++++++ binding/wrap-unicens/wrap-unicens.h | 44 +++++++ conf.d/cmake/config.cmake | 212 +++++++++++++++++++++++++++++++++ conf.d/wgt/config.xml.in | 41 +++++++ conf.d/wgt/icon-service.png | Bin 0 -> 13273 bytes 22 files changed, 1553 insertions(+) create mode 100644 .gitignore create mode 100644 CMakeLists.txt create mode 100644 README.md create mode 100755 autobuild/agl/autobuild create mode 100755 autobuild/linux/autobuild create mode 100644 binding/CMakeLists.txt create mode 100644 binding/amplifier/CMakeLists.txt create mode 100644 binding/amplifier/amplifier.c create mode 100644 binding/amplifier/amplifier.h create mode 100644 binding/binding.c create mode 100644 binding/microphone/CMakeLists.txt create mode 100644 binding/microphone/microphone.c create mode 100644 binding/microphone/microphone.h create mode 100644 binding/slimamp/CMakeLists.txt create mode 100644 binding/slimamp/slimamp.c create mode 100644 binding/slimamp/slimamp.h create mode 100644 binding/wrap-unicens/CMakeLists.txt create mode 100644 binding/wrap-unicens/wrap-unicens.c create mode 100644 binding/wrap-unicens/wrap-unicens.h create mode 100644 conf.d/cmake/config.cmake create mode 100644 conf.d/wgt/config.xml.in create mode 100644 conf.d/wgt/icon-service.png diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9ce8fbb --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +.vscode/ +nbproject/ +build/ +test/ diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..92e59ce --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,19 @@ +################################################################################ +# Copyright 2019 Microchip Technology Inc. and its subsidiaries +# +# 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. +################################################################################ + +CMAKE_MINIMUM_REQUIRED(VERSION 3.3) + +include(${CMAKE_CURRENT_SOURCE_DIR}/conf.d/cmake/config.cmake) diff --git a/README.md b/README.md new file mode 100644 index 0000000..aeeac99 --- /dev/null +++ b/README.md @@ -0,0 +1,134 @@ +# UNICENS Controller Service +This is an AGL service which provides a clear API to control UNICENS network devices. +This service requires the `agl-service-unicens` in order to communicate with the respective network devices. + +# API Description +## Name +The name of the provided API is `unicens-controller`. + +## Verbs +| Name | Description | JSON Parameters | +|-----------------------------|-----------------------------------------------|-------------------------------------------------------------------| +| slimamp_master_volume_set | Set master volume of the slim amplifer. | *Request:* { "value": 0 }
Valid range for `value`: 0..100 | +| amplifier_master_volume_set | Set master volume of the Fiberdyne amplifer. | *Request:* { "value": 0 }
Valid range for `value`: 0..100 | +| microphone_mode_set | Set LED mode of microphone | See section *Verb microphone_mode_set* | + + +### Verb microphone_mode_set +You can set an LED signaling mode with the following parameters. + +| Name | Description | +|---------------|---------------------------------------------------------------------------------------| +| value | none, doa, thinking, speaking, error, waking, ending, cylon, rainbow, wheel | + +## Events +None. + +## Supported Hardware +- Slim Amplifier (Microchip Slim Board Family) +- Fiberdyne Amplifier + +# Setup for a Native Linux Environment +## Prerequisites +- Setup of [AGL App-Framework](https://docs.automotivelinux.org/docs/en/master/devguides/reference/3-installing-binder-daemon.html) from [AGL OBS](https://build.opensuse.org/project/show/isv:LinuxAutomotive) +- MOST Linux Driver + +## Download and Compile the Sources +Since there are two bindings required, we will create one work space and download the repositories here. + +``` +$ mkdir ws_unicens +$ cd ws_unicens +$ git checkout --recurse-submodules https://git.automotivelinux.org/apps/agl-service-unicens +$ git checkout --recurse-submodules https://git.automotivelinux.org/apps/agl-service-unicens-controller +``` + +Now create a `build` folder and build the `agl-service-unicens`. +``` +$ cd agl-service-unicens +$ mkdir build +$ cd build +$ cmake .. +$ make +$ cd .. +``` + +Now create a `build` folder and build the `agl-service-unicens-controller`. +``` +$ cd agl-service-unicens-controller +$ mkdir build +$ cd build +$ cmake .. +$ make +$ cd .. +``` + +## Setup Environment Variables +In the workspace folder setup the following varables. You may set the resulting paths also in your `~/.bashrc` file. +``` +$ export AGL_UCS_PATH=$PWD +$ export AFM_APP_INSTALL_DIR=$PWD/agl-service-unicens/build/package +``` +## Start both Services +It is possible to start both bindings by executing the following command: +``` +$ afb-daemon --name=afb-unicens \ +--binding=$AGL_UCS_PATH/agl-service-unicens-controller/build/package/lib/afb-ucs2-ctrl.so \ +--binding=$AGL_UCS_PATH/agl-service-unicens/build/package/lib/afb-ucs2.so \ +--workdir=$AGL_UCS_PATH/agl-service-unicens/build \ +--roothttp=$AGL_UCS_PATH/agl-service-unicens-controller/htdocs \ +--port=1234 --no-ldpaths --tracereq=common --token= --verbose +``` + +## Test the Services +You may open the testing web interface on [http://localhost:1234/](http://localhost:1234/) or execute +one of the following commands. + +``` +$ curl http://localhost:1234/api/unicens-controller/ping +$ afb-client-demo -H localhost:1234/api?token= unicens-controller ping +$ afb-client-demo -H localhost:1234/api?token= unicens-controller slimamp_master_volume_set "{'value':25}" +$ afb-client-demo -H localhost:1234/api?token= unicens-controller amplifier_master_volume_set "{'value':25}" +$ afb-client-demo -H localhost:1234/api?token= unicens-controller microphone_mode_set "{'value' : 'doa'}" +``` + +# Test on AGL Target Platform +# Prerequisites +- AGL SDK must be installed + +## Download and Cross-Compile the Sources +Execute the follwing commands to download the sources and create the widget. +``` +$ git checkout --recurse-submodules https://git.automotivelinux.org/apps/agl-service-unicens-controller +$ cd agl-service-unicens-controller +$ mkdir build +$ cd build +$ source /opt/agl-sdk/ +$ cmake .. +$ make +$ make widget +``` + +## Install Widget on the Target Platform +Copy the widget to the target and install by executing the following command. +``` +$ afm-util install agl-service-unicens-controller.wgt + +>>> Remember the following response to find out the correct port. +>>> { +>>> "added":"agl-service-unicens-controller@<...>" +>>> } + +$ afm-util info agl-service-unicens-controller@<...> | grep http-port + +>>> Remember the port for the following test commands. +``` + +Please reboot the system and test the binding by executing the following commands. Replace `31022` by the previously +discovered http-port. +``` +afb-client-demo --human 'localhost:31022/api?token=HELLO&uuid=magic' unicens-controller ping +afb-client-demo --human 'localhost:31022/api?token=HELLO&uuid=magic' unicens-controller slimamp_master_volume_set "{'value' : 35}" +afb-client-demo --human 'localhost:31022/api?token=HELLO&uuid=magic' unicens-controller amplifier_master_volume_set "{'value' : 35}" +afb-client-demo --human 'localhost:31022/api?token=HELLO&uuid=magic' unicens-controller microphone_mode_set "{'value' : 'doa'}" +``` diff --git a/autobuild/agl/autobuild b/autobuild/agl/autobuild new file mode 100755 index 0000000..db00c1a --- /dev/null +++ b/autobuild/agl/autobuild @@ -0,0 +1,79 @@ +#!/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 + @if [ "${DEST}" != "${BUILD_DIR}" ]; then \ + mkdir -p ${DEST} && cp ${BUILD_DIR}/*.wgt ${DEST}; \ + fi + +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 + @if [ "${DEST}" != "${BUILD_DIR}" ]; then \ + mkdir -p ${DEST} && cp ${BUILD_DIR}/*.wgt ${DEST}; \ + fi + +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..db00c1a --- /dev/null +++ b/autobuild/linux/autobuild @@ -0,0 +1,79 @@ +#!/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 + @if [ "${DEST}" != "${BUILD_DIR}" ]; then \ + mkdir -p ${DEST} && cp ${BUILD_DIR}/*.wgt ${DEST}; \ + fi + +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 + @if [ "${DEST}" != "${BUILD_DIR}" ]; then \ + mkdir -p ${DEST} && cp ${BUILD_DIR}/*.wgt ${DEST}; \ + fi + +install: build + @cmake --build ${BUILD_DIR} ${INSTALL_ARGS} --target install diff --git a/binding/CMakeLists.txt b/binding/CMakeLists.txt new file mode 100644 index 0000000..88abfaf --- /dev/null +++ b/binding/CMakeLists.txt @@ -0,0 +1,48 @@ +################################################################################ +# Copyright 2019 Microchip Technology Inc. and its subsidiaries +# +# 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_subdirectory(amplifier) +add_subdirectory(slimamp) +add_subdirectory(microphone) +add_subdirectory(wrap-unicens) + +# Add target to project dependency list +PROJECT_TARGET_ADD(ucs2-ctrl) + # Define project Targets + ADD_LIBRARY(${TARGET_NAME} MODULE binding.c) + + TARGET_INCLUDE_DIRECTORIES(${TARGET_NAME} PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}/amplifier + ${CMAKE_CURRENT_SOURCE_DIR}/slimamp + ${CMAKE_CURRENT_SOURCE_DIR}/microphone + ${CMAKE_CURRENT_SOURCE_DIR}/wrap-unicens + ) + + # Binder exposes a unique public entry point + SET_TARGET_PROPERTIES(${TARGET_NAME} PROPERTIES + PREFIX "afb-" + LABELS "BINDING" + OUTPUT_NAME ${TARGET_NAME} + ) + + # Library dependencies (include updates automatically) + TARGET_LINK_LIBRARIES(${TARGET_NAME} + ucs-slimamp + ucs-amplifier + ucs-microphone + ucs-wrapper + ${link_libraries} + ) diff --git a/binding/amplifier/CMakeLists.txt b/binding/amplifier/CMakeLists.txt new file mode 100644 index 0000000..744fee6 --- /dev/null +++ b/binding/amplifier/CMakeLists.txt @@ -0,0 +1,32 @@ +################################################################################ +# Copyright 2019 Microchip Technology Inc. and its subsidiaries +# +# 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(ucs-amplifier) + +# Define targets source files +ADD_LIBRARY(${TARGET_NAME} STATIC amplifier.c) + + # Expose Library Properties + SET_TARGET_PROPERTIES(${TARGET_NAME} PROPERTIES OUTPUT_NAME amplifier) + + # Library dependencies from PKG_REQUIRED_LIST + TARGET_LINK_LIBRARIES(${TARGET_NAME} ${link_libraries} m) + + # Define properties to expose when others use this target + TARGET_INCLUDE_DIRECTORIES(${TARGET_NAME} PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}/../wrap-unicens + ) diff --git a/binding/amplifier/amplifier.c b/binding/amplifier/amplifier.c new file mode 100644 index 0000000..a3b5cc3 --- /dev/null +++ b/binding/amplifier/amplifier.c @@ -0,0 +1,124 @@ +/* + * Copyright 2019 Microchip Technology Inc. and its subsidiaries + * + * 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 +#ifndef AFB_BINDING_VERSION +# define AFB_BINDING_VERSION 3 +#endif + +#include +#include +#include +#include +#include "wrap-unicens.h" +#include "amplifier.h" +#include + +#define NODE_ID ((uint16_t)0x510U) +#define FUNC_VOLUME 0x100U +#define OP_SET 0x00U +#define DEFAULT_VOLUME 0xF0U +#define TX_PAYLOAD_SZ 2U + +static uint8_t _tx_payload[TX_PAYLOAD_SZ] = {OP_SET, DEFAULT_VOLUME}; +static bool _available = false; + +/***************************************************************************** + * Local prototypes + */ +static int get_payload_master_volume(uint8_t sys_vol, uint8_t *payload_ptr, uint8_t payload_sz); +static int amplifier_master_volume_set(uint8_t volume); + +/***************************************************************************** + * API + */ + +extern void amplifier_availablility_changed(uint16_t node_id, bool available) { + if (node_id == NODE_ID) { + AFB_API_DEBUG(afbBindingRoot, "%s: amplifier new availability=%d", __func__, available); + _available = available; + } +} + +extern int amplifier_master_volume_set(uint8_t volume) { + AFB_API_NOTICE(afbBindingRoot, "amplifier_master_volume_set volume=%d", volume); + if (_available == false) { + AFB_API_NOTICE(afbBindingRoot, "%s: node is not available", __func__); + return -1; + } + + if (volume > 100U) { + AFB_API_NOTICE(afbBindingRoot, "%s: invalid volume value %d", __func__, volume); + return -2; // parameter error + } + + int logvalue = abs((int)(log1p((double)volume) * (double)100 / log1p((double)100))); + AFB_API_NOTICE(afbBindingRoot, "%s: logarithic value=%d", __func__, logvalue); + + if (get_payload_master_volume((uint8_t)(logvalue), _tx_payload, TX_PAYLOAD_SZ) != 0) { + AFB_API_NOTICE(afbBindingRoot, "%s: cannot calculate paylaod", __func__); + return -3; // calculation error + } + + // fire message now + AFB_API_DEBUG(afbBindingRoot, "%s: calculated payload: {%02X,%02X}", __func__, _tx_payload[0], _tx_payload[1]); + wrap_ucs_sendmessage_sync(NODE_ID, FUNC_VOLUME, _tx_payload, TX_PAYLOAD_SZ); + + return 0; +} + +/***************************************************************************** + * Device specific helper functions + */ + +static int get_payload_master_volume(uint8_t sys_vol, uint8_t *payload_ptr, uint8_t payload_sz) { + if (payload_sz < 2U) + return -1; + + uint32_t new_vol = (uint32_t)((uint32_t)sys_vol * 255) / 100; // calculate value{0..100} to value{0..255} + + payload_ptr[0] = OP_SET; + payload_ptr[1] = (uint8_t)new_vol; // use 0..255 now + return 0; +} + + +/***************************************************************************** + * JSON API + */ + +extern void amplifier_master_vol_set_api(afb_req_t request) { + int volume = 0; + struct json_object* j_obj = afb_req_json(request); + + AFB_API_DEBUG(afbBindingRoot, "UNICENS-CONTROLLER: %s:%s", __func__, json_object_get_string(j_obj)); + + if (wrap_json_unpack(j_obj, "{s:i}", "value", &volume) == 0) { + AFB_API_DEBUG(afbBindingRoot, "UNICENS-CONTROLLER: decoded value=%d", volume); + + if ((volume >= 0) && (volume <= 100)) { + AFB_API_DEBUG(afbBindingRoot, "amplifier_master_vol_set calling amplifier"); + int res = amplifier_master_volume_set((uint8_t)volume); + AFB_API_DEBUG(afbBindingRoot, "amplifier returning %d", res); + afb_req_success(request, NULL, NULL); + } + else { + afb_req_fail(request, "invalid range of parameter 'value'", NULL); + } + } + else { + afb_req_fail(request, "missing argument 'value'", NULL); + } +} diff --git a/binding/amplifier/amplifier.h b/binding/amplifier/amplifier.h new file mode 100644 index 0000000..e705db4 --- /dev/null +++ b/binding/amplifier/amplifier.h @@ -0,0 +1,27 @@ +/* + * Copyright 2019 Microchip Technology Inc. and its subsidiaries + * + * 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. + */ +#pragma once + +#ifndef AFB_BINDING_VERSION +# define AFB_BINDING_VERSION 3 +#endif +#include + +/* notify events */ +extern void amplifier_availablility_changed(uint16_t node_id, bool available); + +/* JSON API */ +extern void amplifier_master_vol_set_api(afb_req_t request); diff --git a/binding/binding.c b/binding/binding.c new file mode 100644 index 0000000..cebc54a --- /dev/null +++ b/binding/binding.c @@ -0,0 +1,81 @@ +/* + * Copyright 2019 Microchip Technology Inc. and its subsidiaries + * + * 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 +#ifndef AFB_BINDING_VERSION +# define AFB_BINDING_VERSION 3 +#endif + +#include +#include +#include +#include +#include "wrap-unicens.h" +#include "slimamp.h" +#include "amplifier.h" +#include "microphone.h" + +/* callback at load of the binding */ +static int preinit(afb_api_t api) { + AFB_API_NOTICE(afbBindingRoot, "UNICENS-CONTROLLER: PREINIT"); + return 0; +} + +/* callback for starting the service */ +static int init(afb_api_t api) { + AFB_API_NOTICE(afbBindingRoot, "UNICENS-CONTROLLER: INIT"); + wrap_ucs_init(api); + wrap_ucs_subscribe_sync(); + return 0; +} + +static void on_availability_cb(uint16_t node, bool available) { + amplifier_availablility_changed(node, available); + slimamp_availablility_changed(node, available); + microphone_availablility_changed(node, available); +} + +/* callback for handling events */ +static void onevent(afb_api_t api, const char *event, struct json_object *object) { + AFB_API_NOTICE(afbBindingRoot, "UNICENS-CONTROLLER: Event: %s object: %s", event, json_object_get_string(object)); + wrap_ucs_interpret_event(event, object, &on_availability_cb); +} + +static void ping(afb_req_t request) { + AFB_API_NOTICE(afbBindingRoot, "UNICENS-CONTROLLER: Ping successful"); + afb_req_success(request, 0, NULL); +} + +static const afb_verb_t verbs[] = { + {.verb = "ping", .session = AFB_SESSION_NONE, .callback = ping, .auth = NULL}, + {.verb = "slimamp_master_volume_set", .session = AFB_SESSION_NONE, .callback = slimamp_master_vol_set_api, .auth = NULL}, + {.verb = "amplifier_master_volume_set", .session = AFB_SESSION_NONE, .callback = amplifier_master_vol_set_api, .auth = NULL}, + {.verb = "microphone_mode_set", .session = AFB_SESSION_NONE, .callback = microphone_mode_set_api, .auth = NULL}, + {NULL} +}; + +const afb_binding_t afbBindingExport = { + .api = "unicens-controller", + .specification = NULL, + .verbs = verbs, + .preinit = preinit, + .init = init, + .onevent = onevent, + .userdata = NULL, + .provide_class = NULL, + .require_class = NULL, + .require_api = NULL, + .noconcurrency = 0 +}; diff --git a/binding/microphone/CMakeLists.txt b/binding/microphone/CMakeLists.txt new file mode 100644 index 0000000..571274d --- /dev/null +++ b/binding/microphone/CMakeLists.txt @@ -0,0 +1,32 @@ +################################################################################ +# Copyright 2019 Microchip Technology Inc. and its subsidiaries +# +# 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(ucs-microphone) + +# Define targets source files +ADD_LIBRARY(${TARGET_NAME} STATIC microphone.c) + + # Expose Library Properties + SET_TARGET_PROPERTIES(${TARGET_NAME} PROPERTIES OUTPUT_NAME microphone) + + # Library dependencies from PKG_REQUIRED_LIST + TARGET_LINK_LIBRARIES(${TARGET_NAME} ${link_libraries}) + + # Define properties to expose when others use this target + TARGET_INCLUDE_DIRECTORIES(${TARGET_NAME} PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}/../wrap-unicens + ) diff --git a/binding/microphone/microphone.c b/binding/microphone/microphone.c new file mode 100644 index 0000000..dc43cd3 --- /dev/null +++ b/binding/microphone/microphone.c @@ -0,0 +1,153 @@ +/* + * Copyright 2019 Microchip Technology Inc. and its subsidiaries + * + * 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 +#ifndef AFB_BINDING_VERSION +# define AFB_BINDING_VERSION 3 +#endif + +#include +#include +#include +#include +#include "wrap-unicens.h" +#include "microphone.h" + +/***************************************************************************** + * types + */ + +enum microphone_mode +{ + MICROPHONE_MODE_NONE = 0, + MICROPHONE_MODE_DOA = 1, + MICROPHONE_MODE_THINKING = 2, + MICROPHONE_MODE_SPEAKING = 3, + MICROPHONE_MODE_ERROR = 4, + MICROPHONE_MODE_WAKING = 5, + MICROPHONE_MODE_ENDING = 6, + MICROPHONE_MODE_CYLON = 7, + MICROPHONE_MODE_RAINBOW = 8, + MICROPHONE_MODE_WHEEL = 9, + MICROPHONE_MODE_UNKNOWN = 10 +}; + +/***************************************************************************** + * local prototypes + */ + +static int microphone_mode_set(enum microphone_mode mode); + +/***************************************************************************** + * local variables and definitions + */ + +#define NODE_ID ((uint16_t)0x520U) +#define MSG_ID_MODE 0x1001U +#define MSG_OP_SET 0x00U + +#define MSG_MAX_PAYLOAD_SZ 2U +static uint8_t _tx_payload[MSG_MAX_PAYLOAD_SZ]; +static bool _available = false; + +/***************************************************************************** + * functions + */ + +extern void microphone_availablility_changed(uint16_t node_id, bool available) { + if (node_id == NODE_ID) { + AFB_API_DEBUG(afbBindingRoot, "%s: amplifier new availability=%d", __func__, available); + _available = available; + } +} + +static int microphone_mode_set(enum microphone_mode mode) { + AFB_API_NOTICE(afbBindingRoot, "microphone_mode_set value=%d", mode); + if (_available == false) { + AFB_API_NOTICE(afbBindingRoot, "%s: node is not available", __func__); + return -1; + } + + if (mode < MICROPHONE_MODE_UNKNOWN) { + _tx_payload[0] = MSG_OP_SET; + _tx_payload[1] = (uint8_t)mode; + wrap_ucs_sendmessage_sync(NODE_ID, MSG_ID_MODE, _tx_payload, MSG_MAX_PAYLOAD_SZ); + } + else { + AFB_API_NOTICE(afbBindingRoot, "%s: given mode is unknown", __func__); + return -1; + } + + return 0; +} + + +/***************************************************************************** + * JSON API + */ + +extern void microphone_mode_set_api(afb_req_t request) { + char *str_mode = NULL; + struct json_object* j_obj = afb_req_json(request); + + AFB_API_NOTICE(afbBindingRoot, "UNICENS-CONTROLLER: %s:%s", __func__, json_object_get_string(j_obj)); + + if (wrap_json_unpack(j_obj, "{s:s}", "value", &str_mode) == 0) { + AFB_API_NOTICE(afbBindingRoot, "UNICENS-CONTROLLER: decoded value=%s", str_mode); + enum microphone_mode mic_mode = MICROPHONE_MODE_UNKNOWN; + + if (strcmp(str_mode, "none") == 0) { + mic_mode = MICROPHONE_MODE_NONE; + } + else if (strcmp(str_mode, "doa") == 0) { + mic_mode = MICROPHONE_MODE_DOA; + } + else if (strcmp(str_mode, "thinking") == 0) { + mic_mode = MICROPHONE_MODE_THINKING; + } + else if (strcmp(str_mode, "speaking") == 0) { + mic_mode = MICROPHONE_MODE_SPEAKING; + } + else if (strcmp(str_mode, "error") == 0) { + mic_mode = MICROPHONE_MODE_ERROR; + } + else if (strcmp(str_mode, "waking") == 0) { + mic_mode = MICROPHONE_MODE_WAKING; + } + else if (strcmp(str_mode, "ending") == 0) { + mic_mode = MICROPHONE_MODE_ENDING; + } + else if (strcmp(str_mode, "cylon") == 0) { + mic_mode = MICROPHONE_MODE_CYLON; + } + else if (strcmp(str_mode, "rainbow") == 0) { + mic_mode = MICROPHONE_MODE_RAINBOW; + } + else if (strcmp(str_mode, "wheel") == 0) { + mic_mode = MICROPHONE_MODE_WHEEL; + } + + if (mic_mode < MICROPHONE_MODE_UNKNOWN) { + microphone_mode_set(mic_mode); + afb_req_success(request, NULL, NULL); + } + else { + afb_req_fail(request, "argument 'value' is not set to a known value", NULL); + } + } + else { + afb_req_fail(request, "missing argument 'value'", NULL); + } +} \ No newline at end of file diff --git a/binding/microphone/microphone.h b/binding/microphone/microphone.h new file mode 100644 index 0000000..01fbcb2 --- /dev/null +++ b/binding/microphone/microphone.h @@ -0,0 +1,26 @@ +/* + * Copyright 2019 Microchip Technology Inc. and its subsidiaries + * + * 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. + */ +#pragma once + +#ifndef AFB_BINDING_VERSION +# define AFB_BINDING_VERSION 3 +#endif +#include + +/* notification */ +extern void microphone_availablility_changed(uint16_t node_id, bool available); +/* JSON API */ +extern void microphone_mode_set_api(afb_req_t request); diff --git a/binding/slimamp/CMakeLists.txt b/binding/slimamp/CMakeLists.txt new file mode 100644 index 0000000..f2a7d66 --- /dev/null +++ b/binding/slimamp/CMakeLists.txt @@ -0,0 +1,32 @@ +################################################################################ +# Copyright 2019 Microchip Technology Inc. and its subsidiaries +# +# 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(ucs-slimamp) + +# Define targets source files +ADD_LIBRARY(${TARGET_NAME} STATIC slimamp.c) + + # Expose Library Properties + SET_TARGET_PROPERTIES(${TARGET_NAME} PROPERTIES OUTPUT_NAME slimamp) + + # Library dependencies from PKG_REQUIRED_LIST + TARGET_LINK_LIBRARIES(${TARGET_NAME} ${link_libraries}) + + # Define properties to expose when others use this target + TARGET_INCLUDE_DIRECTORIES(${TARGET_NAME} PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}/../wrap-unicens + ) diff --git a/binding/slimamp/slimamp.c b/binding/slimamp/slimamp.c new file mode 100644 index 0000000..1e4f012 --- /dev/null +++ b/binding/slimamp/slimamp.c @@ -0,0 +1,110 @@ +/* + * Copyright 2019 Microchip Technology Inc. and its subsidiaries + * + * 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 +#ifndef AFB_BINDING_VERSION +# define AFB_BINDING_VERSION 3 +#endif + +#include +#include +#include +#include +#include "wrap-unicens.h" + +#define NODE_ID ((uint16_t)0x270U) +#define CONTROL_MASTER 0x07U +#define MUTE_VALUE 0x03FFU +#define MUTE_VALUE_HB 0x03U +#define MUTE_VALUE_LB 0xFFU +#define TX_PAYLOAD_SZ 3U + +static uint8_t _tx_payload[TX_PAYLOAD_SZ] = {CONTROL_MASTER, MUTE_VALUE_HB, MUTE_VALUE_LB}; +static bool _available = false; + +/***************************************************************************** + * Local prototypes + */ +static int slimamp_master_volume_set(uint8_t volume); +static int get_payload_master_volume(uint8_t sys_vol, uint8_t *payload_ptr, uint8_t payload_sz); + +/***************************************************************************** + * API + */ + +extern void slimamp_availablility_changed(uint16_t node_id, bool available) { + if (node_id == NODE_ID) { + _available = available; + } +} + +static int slimamp_master_volume_set(uint8_t volume) { + if (_available == false) + AFB_API_NOTICE(afbBindingRoot, "%s: node is not available", __func__); + return -1; + + if (volume > 100U) + return -2; // parameter error + + if (get_payload_master_volume(volume, _tx_payload, TX_PAYLOAD_SZ) != 0) + return -3; // calculation error + + // fire message now + AFB_API_DEBUG(afbBindingRoot, "%s: calculated payload: {%02X,%02X,%02X}", __func__, _tx_payload[0], _tx_payload[1], _tx_payload[2]); + wrap_ucs_i2cwrite_sync(NODE_ID, _tx_payload, TX_PAYLOAD_SZ); + + return 0; +} + +/***************************************************************************** + * Device specific helper functions + */ + +static int get_payload_master_volume(uint8_t sys_vol, uint8_t *payload_ptr, uint8_t payload_sz) { + if (payload_sz < 3U) + return -1; + + uint16_t tmp = (uint16_t)(0x100U + 0x2FFU - (((int32_t)0x2FFU * (int32_t)sys_vol) / (int32_t)100/*max volume*/)); + payload_ptr[0] = CONTROL_MASTER; + payload_ptr[1] = (uint8_t)((tmp >> 8U) & (uint16_t)0xFFU); //HB:Volume + payload_ptr[2] = (uint8_t)(tmp & (uint16_t)0xFFU); //LB:Volume + return 0; +} + +/***************************************************************************** + * JSON API + */ + +extern void slimamp_master_vol_set_api(afb_req_t request) { + int volume = 0; + struct json_object* j_obj = afb_req_json(request); + + AFB_API_DEBUG(afbBindingRoot, "UNICENS-CONTROLLER: %s:%s", __func__, json_object_get_string(j_obj)); + + if (wrap_json_unpack(j_obj, "{s:i}", "value", &volume) == 0) { + AFB_API_DEBUG(afbBindingRoot, "UNICENS-CONTROLLER: decoded value=%d", volume); + + if ((volume >= 0) && (volume <= 100)) { + slimamp_master_volume_set((uint8_t)volume); + afb_req_success(request, NULL, NULL); + } + else { + afb_req_fail(request, "invalid range of parameter 'value'", NULL); + } + } + else { + afb_req_fail(request, "missing argument 'value'", NULL); + } +} \ No newline at end of file diff --git a/binding/slimamp/slimamp.h b/binding/slimamp/slimamp.h new file mode 100644 index 0000000..bfffdb0 --- /dev/null +++ b/binding/slimamp/slimamp.h @@ -0,0 +1,21 @@ +/* + * Copyright 2019 Microchip Technology Inc. and its subsidiaries + * + * 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. + */ +#pragma once + +/* notification */ +extern void slimamp_availablility_changed(uint16_t node_id, bool available); +/* JSON API */ +extern void slimamp_master_vol_set_api(afb_req_t request); diff --git a/binding/wrap-unicens/CMakeLists.txt b/binding/wrap-unicens/CMakeLists.txt new file mode 100644 index 0000000..ccd3f16 --- /dev/null +++ b/binding/wrap-unicens/CMakeLists.txt @@ -0,0 +1,27 @@ +################################################################################ +# Copyright 2019 Microchip Technology Inc. and its subsidiaries +# +# 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(ucs-wrapper) + +# Define targets source files +ADD_LIBRARY(${TARGET_NAME} STATIC wrap-unicens.c) + + # Expose Library Properties + SET_TARGET_PROPERTIES(${TARGET_NAME} PROPERTIES OUTPUT_NAME wrap-unicens) + + # Library dependencies from PKG_REQUIRED_LIST + TARGET_LINK_LIBRARIES(${TARGET_NAME} ${link_libraries}) diff --git a/binding/wrap-unicens/wrap-unicens.c b/binding/wrap-unicens/wrap-unicens.c new file mode 100644 index 0000000..e5d4570 --- /dev/null +++ b/binding/wrap-unicens/wrap-unicens.c @@ -0,0 +1,228 @@ +/* + * Copyright 2019 Microchip Technology Inc. and its subsidiaries + * + * 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 "wrap-unicens.h" + +typedef struct async_job_ { + wrap_ucs_result_cb_t result_fptr; + void *result_user_ptr; +} async_job_t; + +typedef struct parse_result_ { + int done; + char *str_result; +} parse_result_t; + +static afb_api_t api_handle_ = NULL; + +/* Initializes UNICENS API wrapper */ +extern int wrap_ucs_init(afb_api_t api_handle) { + api_handle_ = api_handle; + return afb_api_require_api(api_handle_, "UNICENS", 1); +} + +/* + * Subscribes to unicens2-binding events. + * \return Returns 0 if successful, otherwise != 0". + */ +extern int wrap_ucs_subscribe_sync(void) { + int err; + + json_object *j_response, *j_query = NULL; + char *error, *info; + + /* Build an empty JSON object */ + if((err = wrap_json_pack(&j_query, "{}"))) { + AFB_API_ERROR(api_handle_, "Failed to create subscribe json object"); + return err; + } + + if((err = afb_api_call_sync(api_handle_, "UNICENS", "subscribe", j_query, &j_response, &error, &info))) { + AFB_API_ERROR(api_handle_, "Fail subscribing to UNICENS events"); + return err; + } + else { + AFB_API_NOTICE(api_handle_, "Subscribed to UNICENS events, res=%s", json_object_to_json_string(j_response)); + json_object_put(j_response); + } + + return 0; +} + +extern int wrap_ucs_interpret_event(const char *event, struct json_object *object, wrap_ucs_availability_cb_t callback) { + int node_id = 0; + int available = false; + + if (strcmp(event, "UNICENS/node-availibility") != 0) { + return -1; // unhandled event + } + + if (wrap_json_unpack(object, "{s:i,s:b}", "node", &node_id, "available", &available) != 0) { + AFB_API_NOTICE(api_handle_, "Parsing node-availibility failed."); + return -2; + } + + if (callback != NULL) { + callback((uint16_t)node_id, (bool)available); + } + + return 0; +} + +/* + * Write I2C command to a network node. + * \param node Node address + * \param ata_ptr Reference to command data + * \param data_sz Size of the command data. Valid values: 1..32. + * \return Returns 0 if successful, otherwise != 0". + */ +extern int wrap_ucs_i2cwrite_sync(uint16_t node, uint8_t *data_ptr, uint8_t data_sz) { + int err; + uint8_t cnt; + + json_object *j_response, *j_query, *j_array = NULL; + char *error, *info; + + j_query = json_object_new_object(); + j_array = json_object_new_array(); + + if(! j_query || ! j_array) { + AFB_API_ERROR(api_handle_, "Failed to create writei2c json objects"); + return -1; + } + + for(cnt = 0U; cnt < data_sz; cnt++) + json_object_array_add(j_array, json_object_new_int(data_ptr[cnt])); + + json_object_object_add(j_query, "node", json_object_new_int(node)); + json_object_object_add(j_query, "data", j_array); + + if((err = afb_api_call_sync(api_handle_, "UNICENS", "writei2c", j_query, &j_response, &error, &info))) { + AFB_API_ERROR(api_handle_, "Failed to call writei2c_sync"); + return err; + } + else { + AFB_API_INFO(api_handle_, "Called writei2c_sync, res=%s", json_object_to_json_string(j_response)); + json_object_put(j_response); + } + + return 0; +} + +extern int wrap_ucs_sendmessage_sync(uint16_t src_addr, uint16_t msg_id, uint8_t *data_ptr, uint8_t data_sz) { + + json_object *j_query, *j_response = NULL; + char *error, *info; + int err = 1; + int node = (int)src_addr; + int msgid = (int)msg_id; + size_t data_size = (size_t)data_sz; + + AFB_API_NOTICE(api_handle_, "--- HAL triggering send message ---"); + + /* skip data attribute if possible, wrap_json_unpack may fail to deal with + * an empty Base64 string */ + if (data_size > 0) + wrap_json_pack(&j_query, "{s:i, s:i, s:Y}", "node", node, "msgid", msgid, "data", data_ptr, data_size); + else + wrap_json_pack(&j_query, "{s:i, s:i}", "node", node, "msgid", msgid); + + AFB_API_NOTICE(api_handle_, "wrap_ucs_sendmessage: jquery=%s", json_object_to_json_string(j_query)); + + err = afb_api_call_sync(api_handle_, "UNICENS", "sendmessage", j_query, &j_response, &error, &info); + + if (err != 0) { + AFB_API_ERROR(api_handle_, "Failed to call wrap_ucs_sendmessage ret=%d", err); + } + else { + AFB_API_NOTICE(api_handle_, "Called wrap_ucs_sendmessage, successful"); + } + + if (j_response != NULL) { + AFB_API_NOTICE(api_handle_, "wrap_ucs_sendmessage, response=%s", json_object_to_json_string(j_response)); + json_object_put(j_response); + } + + return err; +} + +/* ---------------------------- ASYNCHRONOUS API ---------------------------- */ +static void wrap_ucs_i2cwrite_cb(void *closure, /*int status, */struct json_object *j_result, + const char *error, const char * info, afb_api_t api) { + async_job_t *job_ptr; + + AFB_API_INFO(api_handle_, "%s: closure=%p status=?, res=%s", __func__, closure, /*status,*/ json_object_to_json_string(j_result)); + + if(closure) { + job_ptr = (async_job_t *) closure; + + if(job_ptr->result_fptr) + job_ptr->result_fptr(0/*(uint8_t) abs(status)*/, job_ptr->result_user_ptr); + + free(closure); + } +} + +/* + * Write I2C command to a network node. + * \param node Node address + * \param data_ptr Reference to command data + * \param data_sz Size of the command data. Valid values: 1..32. + * \return Returns 0 if successful, otherwise != 0". + */ +extern int wrap_ucs_i2cwrite(uint16_t node, + uint8_t *data_ptr, + uint8_t data_sz, + wrap_ucs_result_cb_t result_fptr, + void *result_user_ptr) +{ + uint8_t cnt; + + json_object *j_query, *j_array = NULL; + async_job_t *job_ptr = NULL; + + j_query = json_object_new_object(); + j_array = json_object_new_array(); + + if(! j_query || ! j_array) { + AFB_API_ERROR(api_handle_, "Failed to create writei2c json objects"); + return -1; + } + + for(cnt = 0U; cnt < data_sz; cnt++) + json_object_array_add(j_array, json_object_new_int(data_ptr[cnt])); + + json_object_object_add(j_query, "node", json_object_new_int(node)); + json_object_object_add(j_query, "data", j_array); + + job_ptr = malloc(sizeof(async_job_t)); + + if(! job_ptr) { + AFB_API_ERROR(api_handle_, "Failed to create async job object"); + json_object_put(j_query); + return -2; + } + + job_ptr->result_fptr = result_fptr; + job_ptr->result_user_ptr = result_user_ptr; + + afb_api_call(api_handle_, "UNICENS", "writei2c", j_query, wrap_ucs_i2cwrite_cb, job_ptr); + return 0; +} diff --git a/binding/wrap-unicens/wrap-unicens.h b/binding/wrap-unicens/wrap-unicens.h new file mode 100644 index 0000000..a6e2f43 --- /dev/null +++ b/binding/wrap-unicens/wrap-unicens.h @@ -0,0 +1,44 @@ +/* + * Copyright 2019 Microchip Technology Inc. and its subsidiaries + * + * 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. + */ +#pragma once + +#ifndef AFB_BINDING_VERSION +# define AFB_BINDING_VERSION 3 +#endif + +#include +#include +#include +#include + +extern int wrap_ucs_init(afb_api_t apiHandle); + +/* Asynchronous API: result callback */ +typedef void (*wrap_ucs_availability_cb_t)(uint16_t node, bool available); +typedef void (*wrap_ucs_result_cb_t)(uint8_t result, void *user_ptr); + +/* Asynchronous API: functions */ +extern int wrap_ucs_i2cwrite(uint16_t node, + uint8_t *data_ptr, + uint8_t data_sz, + wrap_ucs_result_cb_t result_fptr, + void *result_user_ptr); + +/* Synchronous API: functions */ +extern int wrap_ucs_subscribe_sync(void); +extern int wrap_ucs_interpret_event(const char *event, struct json_object *object, wrap_ucs_availability_cb_t callback); +extern int wrap_ucs_i2cwrite_sync(uint16_t node, uint8_t *data_ptr, uint8_t data_sz); +extern int wrap_ucs_sendmessage_sync(uint16_t src_addr, uint16_t msg_id, uint8_t *data_ptr, uint8_t data_sz); diff --git a/conf.d/cmake/config.cmake b/conf.d/cmake/config.cmake new file mode 100644 index 0000000..6219fad --- /dev/null +++ b/conf.d/cmake/config.cmake @@ -0,0 +1,212 @@ +########################################################################### +# Copyright 2015, 2016, 2017 IoT.bzh +# +# author: Fulup Ar Foll +# unicens-controller: Tobias Jahnke =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.") + +# 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-ucs2-ctrl.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/wgt/config.xml.in b/conf.d/wgt/config.xml.in new file mode 100644 index 0000000..c0ff952 --- /dev/null +++ b/conf.d/wgt/config.xml.in @@ -0,0 +1,41 @@ + + + + + @PROJECT_NAME@ + + + @PROJECT_DESCRIPTION@ + @PROJECT_AUTHOR@ <@PROJECT_AUTHOR_MAIL@> + @PROJECT_LICENSE@ + + + + + + + + + + + + + + + + + diff --git a/conf.d/wgt/icon-service.png b/conf.d/wgt/icon-service.png new file mode 100644 index 0000000..3aeb6f0 Binary files /dev/null and b/conf.d/wgt/icon-service.png differ -- cgit 1.2.3-korg