From 6a543c98824d8a0c91fb24b9d35cc542c75ce01b Mon Sep 17 00:00:00 2001 From: Joakim Roubert Date: Tue, 26 Nov 2024 16:09:26 +0100 Subject: [PATCH] vapix-sh: Add example that uses shellscript only and not C This example does the same thing as the VAPIX example written in C, but uses a POSIX shellscript to implement the application instead. It shows how simpler applications can be written with just a shellscript but still bring value, which is good for those who are not C-savvy. (Whereas those who want to build more advanced applications with VAPIX would probably opt for the C version to build upon.) Change-Id: I6f0e874996e69e6319107931bbc93b81ffa40db9 Signed-off-by: Joakim Roubert --- README.md | 4 + vapix-sh/Dockerfile | 12 ++ vapix-sh/README.md | 166 ++++++++++++++++++++++ vapix-sh/app/LICENSE | 257 ++++++++++++++++++++++++++++++++++ vapix-sh/app/Makefile | 6 + vapix-sh/app/manifest.json | 17 +++ vapix-sh/app/vapix_example_sh | 58 ++++++++ 7 files changed, 520 insertions(+) create mode 100644 vapix-sh/Dockerfile create mode 100644 vapix-sh/README.md create mode 100644 vapix-sh/app/LICENSE create mode 100644 vapix-sh/app/Makefile create mode 100644 vapix-sh/app/manifest.json create mode 100755 vapix-sh/app/vapix_example_sh diff --git a/README.md b/README.md index 71ad7df..deb161f 100644 --- a/README.md +++ b/README.md @@ -67,6 +67,10 @@ Below is the list of examples available in the repository. - [vapix](./vapix/) - An example in C that retrieves VAPIX credentials over D-Bus and makes VAPIX calls over a loopback interface. + +- [vapix-sh](./vapix-sh/) + + - A shellscript example that retrieves VAPIX credentials over D-Bus and makes VAPIX calls over a loopback interface. - [vdo-larod](./vdo-larod/) - An example in C that loads a pretrained person-car classification model to the [Machine learning API (Larod)](https://axiscommunications.github.io/acap-documentation/docs/api/native-sdk-api.html#machine-learning-api-larod) and then uses the [Video capture API (VDO)](https://axiscommunications.github.io/acap-documentation/docs/api/native-sdk-api.html#video-capture-api-vdo) to fetch video frames in YUV format and finally run inference. - [vdo-opencl-filtering](./vdo-opencl-filtering/) diff --git a/vapix-sh/Dockerfile b/vapix-sh/Dockerfile new file mode 100644 index 0000000..42eb536 --- /dev/null +++ b/vapix-sh/Dockerfile @@ -0,0 +1,12 @@ +ARG ARCH=aarch64 +ARG VERSION=12.1.0 +ARG UBUNTU_VERSION=24.04 +ARG REPO=axisecp +ARG SDK=acap-native-sdk + +FROM ${REPO}/${SDK}:${VERSION}-${ARCH}-ubuntu${UBUNTU_VERSION} + +WORKDIR /opt/app +COPY ./app . +RUN . /opt/axis/acapsdk/environment-setup* && \ + acap-build . diff --git a/vapix-sh/README.md b/vapix-sh/README.md new file mode 100644 index 0000000..31e2c09 --- /dev/null +++ b/vapix-sh/README.md @@ -0,0 +1,166 @@ +*Copyright (C) 2024, Axis Communications AB, Lund, Sweden. All Rights Reserved.* + +# ACAP application calling VAPIX APIs + +This example shows how an ACAP application can call +[VAPIX](https://www.axis.com/vapix-library) APIs, +Axis open APIs. + +> [!NOTE] +> This ACAP application does the same thing as the [vapix](../vapix) example +> in this repo, but instead of C code this one implements the same +> functionality with a POSIX shell script. + +The collection of VAPIX APIs enables a wide selection of functionality to an +ACAP application. Some examples: + +- Call [basic device information](https://www.axis.com/vapix-library/subjects/t10175981/section/t10132180/display?section=t10132180-t10132179) + API to get a device's serial number and system-on-chip (SoC). +- Call [list installed applications](https://www.axis.com/vapix-library/subjects/t10102231/section/t10036126/display?section=t10036126-t10010644) + API to get installed ACAP applications. + +## Outline of example + +1. Retrieve VAPIX credentials through a D-Bus API. +2. Use curl to make a HTTP POST request to VAPIX API **Basic device + information** on dedicated local host IP `127.0.0.12`. +3. Parse out fields from the answer + +## Practical information + +### API to get VAPIX credentials + +- The credentials should be re-fetched each time the ACAP application starts + and should only be kept in memory by the ACAP application, not stored in any + file. +- See more information of this feature in [ACAP documentation](https://axiscommunications.github.io/acap-documentation/docs/develop/VAPIX-access-for-ACAP-applications.html). + +#### Versions + +- The feature to call VAPIX APIs was introduced in AXIS OS 11.6 as Beta. +- The format of the D-Bus API to get VAPIX credentials changed in 11.8. +- The D-Bus API to get VAPIX credentials reached General Availability in 11.9. + +### VAPIX APIs + +- Some VAPIX APIs may work with GET, but it's recommended to use POST for all + API calls since it should cover all use cases of GET. +- The response format varies for different VAPIX APIs, but common response formats + are JSON, XML and text. See the VAPIX documentation of the specific API for + information of format. + +### Global proxy configuration + +- If a device has set global device proxy, it may cause issues with reaching the local host IP + `127.0.0.12` from the ACAP application. +- To make the local host IP reachable when global device proxies are configured, add `127.0.0.12` to + the `No proxy` list. This can be done via either: + - The VAPIX + [Network Settings API](https://developer.axis.com/vapix/network-video/network-settings-api#setglobalproxyconfiguration-1). + - Browse to the network page at `http:///index.html#system/network` and section + `Global proxies`. + +## Getting started + +These instructions will guide you on how to execute the code. Below is the +structure and scripts used in the example: + +```sh +vapix +├── app +│ ├── vapix_example_sh +│ ├── LICENSE +│ ├── Makefile +│ └── manifest.json +├── Dockerfile +└── README.md +``` + +- **app/vapix_example_sh** - A POSIX shellscript that comprises the application. +- **app/LICENSE** - Text file which lists all open source licensed source code distributed with the application. +- **app/Makefile** - Makefile containing the build and link instructions for building the ACAP application. +- **app/manifest.json** - Defines the application and its configuration. This includes additional parameters. +- **Dockerfile** - Docker file with the specified Axis toolchain and API container to build the example specified. +- **README.md** - Step by step instructions on how to run the example. + +### How to run the code + +Below is the step by step instructions on how to execute the program. So +basically starting with the generation of the .eap file to running it on a +device. + +#### Build the application + +Standing in your working directory run the following commands: + +> [!NOTE] +> +> Depending on the network you are connected to, you may need to add proxy settings. +> The file that needs these settings is: `~/.docker/config.json`. For reference please see +> https://docs.docker.com/network/proxy and a +> [script for Axis devices](https://axiscommunications.github.io/acap-documentation/docs/develop/build-install-run.html#configure-network-proxy-settings) in the ACAP documentation. + +```sh +docker build --tag --build-arg ARCH= . +``` + +- `` is the name to tag the image with, e.g., `vapix_example_sh:1.0` +- `` is the SDK architecture, `armv7hf` or `aarch64`. + +Copy the result from the container image to a local directory `build`: + +```sh +docker cp $(docker create ):/opt/app ./build +``` + +The `build` directory contains the build artifacts, where the ACAP application +is found with suffix `.eap`, depending on which SDK architecture that was +chosen, one of these files should be found: + +- `vapix_example_sh_1_0_0_aarch64.eap` +- `vapix_example_sh_1_0_0_armv7hf.eap` + +#### Install and start the application + +Browse to the application page of the Axis device: + +```sh +http:///index.html#apps +``` + +- Click on the tab `Apps` in the device GUI +- Enable `Allow unsigned apps` toggle +- Click `(+ Add app)` button to upload the application file +- Browse to the newly built ACAP application, depending on architecture: + - `vapix_example_sh_1_0_0_aarch64.eap` + - `vapix_example_sh_1_0_0_armv7hf.eap` +- Click `Install` +- Run the application by enabling the `Start` switch + +#### The expected output + +The application log can be found by either + +- Browse to `http:///axis-cgi/admin/systemlog.cgi?appname=vapix_example_sh`. +- Browse to the application page and click the `App log`. + +The log shows a few parsed values from the VAPIX API response. + +```text +----- Contents of SYSTEM_LOG for 'vapix_example_sh' ----- + +[ INFO ] vapix_example_sh[9731]: Curl version 8.6.0 +[ INFO ] vapix_example_sh[9731]: ProdShortName: AXIS Q3536-LVE +[ INFO ] vapix_example_sh[9731]: Soc: Axis Artpec-8 +[ INFO ] vapix_example_sh[9731]: SocSerialNumber: ABCD1234-0101ABAB +``` + +> [!NOTE] +> +> The curl and Jansson versions mentioned in the example log are only for representation +> purpose. They may vary according to the library version available and linked from +> AXIS OS on which the application runs. + +## License + +**[Apache License 2.0](../LICENSE)** diff --git a/vapix-sh/app/LICENSE b/vapix-sh/app/LICENSE new file mode 100644 index 0000000..4ba926f --- /dev/null +++ b/vapix-sh/app/LICENSE @@ -0,0 +1,257 @@ + + Apache License + Version 2.0, January 2004 + https://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 2024 Axis Communications AB + + 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 + + https://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. + +================================================================================ + Third party licenses +================================================================================ + +-------------------------------------------------------------------------------- +curl license +-------------------------------------------------------------------------------- + +COPYRIGHT AND PERMISSION NOTICE + +Copyright (C) Daniel Stenberg, , and many +contributors, see the THANKS file. + +All rights reserved. + +Permission to use, copy, modify, and distribute this software for any purpose +with or without fee is hereby granted, provided that the above copyright +notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN +NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of a copyright holder shall not +be used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization of the copyright holder. + +-------------------------------------------------------------------------------- +jansson license +-------------------------------------------------------------------------------- + +Copyright (c) 2009-2020 Petri Lehtinen + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/vapix-sh/app/Makefile b/vapix-sh/app/Makefile new file mode 100644 index 0000000..2a95a5c --- /dev/null +++ b/vapix-sh/app/Makefile @@ -0,0 +1,6 @@ +.PHONY: all clean + +all: + +clean: + rm -rf *.eap* *_LICENSE.txt package.conf* param.conf diff --git a/vapix-sh/app/manifest.json b/vapix-sh/app/manifest.json new file mode 100644 index 0000000..20b7933 --- /dev/null +++ b/vapix-sh/app/manifest.json @@ -0,0 +1,17 @@ +{ + "schemaVersion": "1.7.2", + "acapPackageConf": { + "setup": { + "appName": "vapix_example_sh", + "vendor": "Axis Communications", + "embeddedSdkVersion": "3.0", + "runMode": "never", + "version": "1.0.0" + } + }, + "resources": { + "dbus": { + "requiredMethods": ["com.axis.HTTPConf1.VAPIXServiceAccounts1.GetCredentials"] + } + } +} diff --git a/vapix-sh/app/vapix_example_sh b/vapix-sh/app/vapix_example_sh new file mode 100755 index 0000000..53161f9 --- /dev/null +++ b/vapix-sh/app/vapix_example_sh @@ -0,0 +1,58 @@ +#!/bin/sh -eu + +USERNAME=example-vapix-user +BASEURL=http://127.0.0.12/axis-cgi + +# Get the VAPIX credentials from D-Bus +CREDENTIALS=$(dbus-send --system \ + --print-reply \ + --dest=com.axis.HTTPConf1 \ + /com/axis/HTTPConf1/VAPIXServiceAccounts1 \ + com.axis.HTTPConf1.VAPIXServiceAccounts1.GetCredentials \ + string:"$USERNAME") +CREDENTIALS=${CREDENTIALS#*\"} +CREDENTIALS=${CREDENTIALS%\"*} + +# Function that does VAPIX requests +request() { + [ $# -eq 2 ] || { + echo "Error: expected 2 parameters but got $#" >&2 + return 1 + } + + response=$(curl -s -u "$CREDENTIALS" -H 'Content-Type: application/json' -d "$1" "$BASEURL/$2") + + error=$(echo "$response" | jq -r '.error.message // empty') + [ -z "$error" ] || { + echo "Error: $error" >&2 + return 1 + } + echo "$response" +} + +# Function that reads and prints a specific item (second parameter) from a +# basic device info property list (provided as the first parameter) +read_property() { + [ $# -eq 2 ] || { + echo "Error: expected 2 parameters but got $#" >&2 + return 1 + } + + echo "$2: $(echo "$1" | jq -r ".data.propertyList.$2 // empty")" +} + +# Retrieve and print curl version +curl_ver=$(curl --version) +curl_ver=${curl_ver#* } +curl_ver=${curl_ver%% *} +echo "Curl version $curl_ver" + +# Do VAPIX request for basic device info +REQUEST='{"apiVersion": "1.3", "method": "getAllProperties"}' +DATA=$(request "$REQUEST" basicdeviceinfo.cgi) + +# Print selected parts od the retrieved basic device info +read_property "$DATA" ProdShortName +read_property "$DATA" Soc +read_property "$DATA" SocSerialNumber +