{"id":45665,"date":"2018-01-16T16:24:23","date_gmt":"2018-01-16T21:24:23","guid":{"rendered":"http:\/\/www.eagleeyenetworks.com\/?p=45665"},"modified":"2023-08-30T19:35:42","modified_gmt":"2023-08-31T00:35:42","slug":"annotation-api","status":"publish","type":"post","link":"https:\/\/www.een.com\/sv\/blog\/annotation-api\/","title":{"rendered":"Annotation API"},"content":{"rendered":"\n<h2 class=\"wp-block-heading\">Overview<\/h2>\n\n\n\n<p><span style=\"font-weight: 400;\">In this project, we provide a referential Python script demonstrating the use of the Eagle Eye Networks (EEN) API to add GPS annotation data to a camera device\u2019s timeline. &nbsp;&nbsp;The script onlines the common steps to properly creating and updating new annotation objects. &nbsp;Our goal is to prepare developers with the know-how to create and interact with any custom annotation data they may need for their particular application.<\/span><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Before You Begin<\/h2>\n\n\n\n<p><span style=\"font-weight: 400;\">You will need to collect a few items before we begin.<\/span><\/p>\n\n\n\n<ol class=\"wp-block-list\"><li><span style=\"font-weight: 400;\">EEN user account <\/span><i><span style=\"font-weight: 400;\">without<\/span><\/i><span style=\"font-weight: 400;\"> two-factor authentication enabled since the demo code doesn\u2019t support this feature. \u00a0<\/span><\/li><li><span style=\"font-weight: 400;\">ESN information for the camera to which you\u2019d like to add annotations. <\/span><\/li><li><span style=\"font-weight: 400;\">EEN developer account and API key. \u00a0See <a href=\"https:\/\/developer.eagleeyenetworks.com\/docs\/getting-started\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/developer.eagleeyenetworks.com\/docs\/getting-started<\/a> for details.<\/span><\/li><li>Install Docker. See link <a href=\"https:\/\/docs.docker.com\/engine\/installation\/\">https:\/\/docs.docker.com\/engine\/installation\/<\/a> for details.<\/li><li><span style=\"font-weight: 400;\">Install Git. \u00a0See <\/span><a href=\"https:\/\/git-scm.com\/book\/en\/v2\/Getting-Started-Installing-Git\"><span style=\"font-weight: 400;\">https:\/\/git-scm.com\/book\/en\/v2\/Getting-Started-Installing-Git<\/span><\/a><span style=\"font-weight: 400;\"> for details.<\/span><\/li><li><span style=\"font-weight: 400;\">Optionally, if you plan to add your own annotation types, you will need to provide a unique namespace identifier to the API. \u00a0Please email support to request a unique namespace for your data. Demo uses namespace 300 for GPS data.<\/span><\/li><\/ol>\n\n\n\n<h2 class=\"wp-block-heading\">Running the Demo<\/h2>\n\n\n\n<p><span style=\"font-weight: 400;\">To make installing and running the demo easier, we created a Docker image containing all of the code and dependencies needed to make it work.&nbsp; In this section, we walk you through the steps to download the code, build a Docker image, run a Docker container and execute the demo script.<\/span><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Download the code from Github<\/h2>\n\n\n\n<p>Open a shell and run the following command to download the code to your local machine:<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><span style=\"font-weight: 400;\">Build the Docker Image<\/span><\/h2>\n\n\n\n<p><span style=\"font-weight: 400;\">Navigate into the <\/span><i><span style=\"font-weight: 400;\">annotation-api-demo<\/span><\/i><span style=\"font-weight: 400;\"> folder.&nbsp;<\/span><\/p>\n\n\n\n<p>Run \u201cdocker build\u201d to create the image.&nbsp; We recommend tagging the image to make it easier to reference later.&nbsp; You can do this with the -t option.<\/p>\n\n\n\n<p>The Docker image is now ready for use in a container.&nbsp; You can verify this by running the \u201cdocker images\u201d command.&nbsp; You should see <em>gps-demo-image<\/em> listed in the results.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Create and Run the Container<\/h2>\n\n\n\n<p>Use the \u201cdocker run\u201d command to create a Docker container from the image.&nbsp; Verify that the container is running properly with the \u201cdocker ps\u201d command.&nbsp; If all is well, you will see the \u201cgps-demo\u201d container listed in the output.&nbsp;&nbsp; We use the &#8211;name option to give the container an easy name to remember.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Run the Python Demo Script<\/h2>\n\n\n\n<p>Use \u201cdocker exec\u201d to open a bash shell in the container then verify the contents of the current folder (\/code) by running the \u201cls\u201d command.<\/p>\n\n\n\n<p>You should see four files listed.<\/p>\n\n\n\n<div class=\"table-1\">\n<table width=\"100%\">\n<tbody>\n<tr>\n<td width=\"132\"><strong>Filename<\/strong><\/td>\n<td width=\"492\"><strong>Description<\/strong><\/td>\n<\/tr>\n<tr>\n<td width=\"132\">eenclient.py<\/td>\n<td width=\"492\">Simple Python API client.&nbsp; Supports authentication, authorization and annotation endpoints.<\/td>\n<\/tr>\n<tr>\n<td width=\"132\">gpsparse.py<\/td>\n<td width=\"492\">Python module with helper functions for parsing data from the GPS.txt file located in this project.<\/td>\n<\/tr>\n<tr>\n<td width=\"132\">gps.py<\/td>\n<td width=\"492\">The main demo script showing how to add and update annotations using the EEN API.<\/td>\n<\/tr>\n<tr>\n<td width=\"132\">gps.txt<\/td>\n<td width=\"492\">Text file containing GPS waypoints.<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n\n\n\n<p>The primary script is named \u201cgps.py\u201d.&nbsp; It contains the high level logic to create and update GPS annotation data using the EEN API.&nbsp; You can run this script with the \u201c-h\u201d option to get a detailed description of the input arguments it accepts.&nbsp; All positional arguments are required including your developer API key, username, password and camera ESN.<\/p>\n\n\n\n<p>Try running the script using values from your account following the example below.&nbsp; (Note: The start time is taken from the GPS.txt file if you don\u2019t include one with the &#8211;start option.&nbsp; The call will fail if start time falls outside of retention for the ESN.)<\/p>\n\n\n\n<p>When using the \u201cheartbeat\u201d approach to updating an annotation, the first GPS coordinate is stored in the \u201cstart\u201d attribute.&nbsp; The remaining coordinates are added to the \u201c_hb\u201d attribute representing changes to the annotation over time.&nbsp; You can clearly see this behavior in the logs above.<\/p>\n\n\n\n<p>Now that you have seen how to run the demo, let\u2019s walk through the code itself.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Source Code Walkthrough<\/h2>\n\n\n\n<p>We start off by authenticating and authorizing the user then fetching the device details to ensure everything is setup properly.&nbsp; To interface with the EEN API, we use an instance of the EENClient class which provides methods to wrap all the logic required to build a proper API request.&nbsp; The source code for this class is in the <em>eenclient.py<\/em> file.<\/p>\n\n\n\n<p>Next, we initialize some variables and create an instance of TimeStepTacker to help us compute time intervals between GPS coordinate readings in the GPS.txt file.<\/p>\n\n\n\n<p>To track timestamps for the annotation, we use the current_datetime_object object.&nbsp; If you pass a starting timestamp on the command line then we set current_datetime_object to that value and the annotation will start at that time.&nbsp; Otherwise, the starting timestamp will default to the timestamp for the first reading in the GPS.txt file.<\/p>\n\n\n\n<p>The core of the script loops through the coordinates in the GPS.txt file.&nbsp; For each new coordinate, we calculate the time elapsed since the previous reading, update the current_datetime_object and convert the date object into a string format consumable by the API.<\/p>\n\n\n\n<p>We then read the next three lines in the file to parse out the GPS longitude, latitude, and velocity readings saving the results in the data dictionary.<\/p>\n\n\n\n<p>Now we are ready to send coordinates to the API.&nbsp; We use the uuid variable to track the unique identifier of the annotation we are creating.&nbsp; The first time through the loop, this value will be None, so we create the annotation using the client.createAnnotation method.&nbsp;&nbsp; On subsequent passes through the loop, we use the client.updateAnnotation method to update the annotation with the new coordinate values.<\/p>\n\n\n\n<p>For the purposes of this demonstration, we set an arbitrary limit of five coordinates to the annotation.&nbsp; After adding the fifth, we close the annotation using the client.updateAnnotation method with the update type set to \u2018end\u2019.<\/p>\n\n\n\n<p>Lastly, we verify the annotation by reading it back with the client.getAnnotations method and printing the results to the console.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Conclusion<\/h2>\n\n\n\n<p>Our goal with this demonstration was to give you a real-world example of using the EEN API to add custom annotation data.&nbsp; We hope the sample code gives you the information you need to add custom annotations to your particular application.&nbsp;&nbsp; In summary, the main steps are to setup an API key, authenticate and authorize with your account credentials, obtain a namespace identifier for your data and make the create and update calls using the annotation API endpoints.<\/p>\n\n\n\n<p>For additional information on the API, please checkout our documentation here:<br><a href=\"https:\/\/developer.eagleeyenetworks.com\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/developer.eagleeyenetworks.com<\/a>.\u00a0 You\u2019ll find a detailed section on Annotations as well as many other aspects of the Eagle Eye platform.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Overview In this project, we provide a referential Python script demonstrating the use of the Eagle Eye Networks (EEN) API to add GPS annotation data to a camera device\u2019s timeline. &hellip;<\/p>\n<p class=\"read-more\"> <a class=\"\" href=\"https:\/\/www.een.com\/sv\/blog\/annotation-api\/\"> <span class=\"screen-reader-text\">Annotation API<\/span> L\u00e4s mer &raquo;<\/a><\/p>\n","protected":false},"author":3155,"featured_media":45650,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"_relevanssi_hide_post":"","_relevanssi_hide_content":"","_relevanssi_pin_for_all":"","_relevanssi_pin_keywords":"","_relevanssi_unpin_keywords":"","_relevanssi_related_keywords":"","_relevanssi_related_include_ids":"","_relevanssi_related_exclude_ids":"","_relevanssi_related_no_append":"","_relevanssi_related_not_related":"","_relevanssi_related_posts":"46193,7056,95973,62918,8127,101211","_relevanssi_noindex_reason":"","footnotes":""},"categories":[232],"tags":[1279,1275,1273,1272],"class_list":["post-45665","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-technology","tag-apis","tag-cloud-computing","tag-cloud-video-surveillance","tag-video-management-software"],"acf":[],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/www.een.com\/sv\/wp-json\/wp\/v2\/posts\/45665","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.een.com\/sv\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.een.com\/sv\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.een.com\/sv\/wp-json\/wp\/v2\/users\/3155"}],"replies":[{"embeddable":true,"href":"https:\/\/www.een.com\/sv\/wp-json\/wp\/v2\/comments?post=45665"}],"version-history":[{"count":0,"href":"https:\/\/www.een.com\/sv\/wp-json\/wp\/v2\/posts\/45665\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.een.com\/sv\/wp-json\/wp\/v2\/media\/45650"}],"wp:attachment":[{"href":"https:\/\/www.een.com\/sv\/wp-json\/wp\/v2\/media?parent=45665"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.een.com\/sv\/wp-json\/wp\/v2\/categories?post=45665"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.een.com\/sv\/wp-json\/wp\/v2\/tags?post=45665"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}