{"id":13506112,"url":"https://github.com/Orange-OpenSource/python-ngsild-client","last_synced_at":"2025-03-30T03:30:36.226Z","repository":{"id":37700060,"uuid":"365250984","full_name":"Orange-OpenSource/python-ngsild-client","owner":"Orange-OpenSource","description":"ngsildclient is a Python library dedicated to NGSI-LD. It's both a NGSI-LD API client and a toolbox to create and manipulate NGSI-LD entities effortlessly.","archived":false,"fork":false,"pushed_at":"2023-08-14T23:10:18.000Z","size":4449,"stargazers_count":13,"open_issues_count":6,"forks_count":8,"subscribers_count":18,"default_branch":"master","last_synced_at":"2024-11-01T04:35:03.489Z","etag":null,"topics":["fiware","ngsi-ld","ngsi-ld-client","python-library","python-wrapper"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Orange-OpenSource.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2021-05-07T13:57:47.000Z","updated_at":"2024-02-15T17:21:44.000Z","dependencies_parsed_at":"2023-01-25T16:01:28.796Z","dependency_job_id":null,"html_url":"https://github.com/Orange-OpenSource/python-ngsild-client","commit_stats":{"total_commits":298,"total_committers":3,"mean_commits":99.33333333333333,"dds":"0.010067114093959773","last_synced_commit":"99872c77e2ce5696dc24df0ff3aed32a63df7f31"},"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Orange-OpenSource%2Fpython-ngsild-client","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Orange-OpenSource%2Fpython-ngsild-client/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Orange-OpenSource%2Fpython-ngsild-client/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Orange-OpenSource%2Fpython-ngsild-client/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Orange-OpenSource","download_url":"https://codeload.github.com/Orange-OpenSource/python-ngsild-client/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246273533,"owners_count":20750904,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["fiware","ngsi-ld","ngsi-ld-client","python-library","python-wrapper"],"created_at":"2024-08-01T01:00:34.823Z","updated_at":"2025-03-30T03:30:34.796Z","avatar_url":"https://github.com/Orange-OpenSource.png","language":"Python","funding_links":[],"categories":["Open-Source FIWARE from third parties"],"sub_categories":["Processing"],"readme":"# The ngsildclient library\n\n[![NGSI-LD badge](https://img.shields.io/badge/NGSI-LD-red.svg)](https://www.etsi.org/deliver/etsi_gs/CIM/001_099/009/01.02.01_60/gs_CIM009v010201p.pdf)\n[![SOF support badge](https://nexus.lab.fiware.org/repository/raw/public/badges/stackoverflow/fiware.svg)](http://stackoverflow.com/questions/tagged/fiware)\n\u003cbr\u003e\n[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)\n[![Read the Docs](https://img.shields.io/readthedocs/ngsildclient)](https://ngsildclient.readthedocs.io/en/latest/index.html)\n\u003cbr\u003e\n[![deploy status](https://github.com/Orange-OpenSource/python-ngsild-client/workflows/CI/badge.svg)](https://github.com/Orange-OpenSource/python-ngsild-client/actions)\n[![PyPI](https://img.shields.io/pypi/v/ngsildclient.svg)](https://pypi.org/project/ngsildclient/)\n[![Python version](https://img.shields.io/pypi/pyversions/ngsildclient)](https://pypi.org/project/ngsildclient/)\n\n\n## Overview\n\n **ngsildclient** is a Python library dedicated to NGSI-LD.\n \n It combines :\n\n - a toolbox to create and modify NGSI-LD entities effortlessly\n - a NGSI-LD API client to interact with a Context Broker\n\n## Features\n\n### Build NGSI-LD entities\n\nngsildclient aims at :\n\n- programmatically generate NGSI-LD entities\n- load entities from JSON-LD payloads\n\nFour primitives are provided `prop()`, `gprop()`, `tprop()`, `rel()` to build respectively a Property, GeoProperty, TemporalProperty and Relationship.\n\nAn Entity is backed by a Python dictionary that stores the JSON-LD payload.\nThe library operates the mapping between the Entity's attributes and their JSON-LD counterpart, allowing to easily manipulate NGSI-LD value and metadata directly in Python.\n\n### Features list\n\n- primitives to build properties and relationships (chainable)\n- benefit from uri naming convention, omit scheme and entity's type, e.g. `parking = Entity(\"OffStreetParking\", \"Downtown1\")`\n- support dot-notation facility, e.g. `reliability = parking[\"availableSpotNumber.reliability\"]`\n- easily manipulate a property's value, e.g. `reliability.value = 0.8`\n- easily manipulate a property's metadata, e.g. `reliability.datasetid = \"dataset1\"`\n- support nesting\n- support multi-attribute\n- load/save to file\n- load from HTTP\n- load well-known sample entities, e.g.  `parking = Entity.load(SmartDataModels.SmartCities.Parking.OffStreetParking)`\n- provide helpers to ease building some structures, e.g. PostalAddress\n- pretty-print entity and properties\n\n### Interact with the Context Broker\n\nTwo clients are provided, `Client` and `AsyncClient` respectively for synchronous and asynchronous modes.\n\nPrefer the synchronous one when working in interactive mode, for example to explore and visualize context data in a Jupyter notebook.\nPrefer the async one if you're looking for performance, for example to develop a real-time NGSI-LD Agent with a high data-acquisition frequency rate.\n\n### Features list\n\n - synchronous and asynchronous clients\n - support batch operations\n - support pagination : transparently handle pagination (sending as many requests as needed under the hood)\n - support auto-batch : transparently divide into many batch requests if needed\n - support queries and alternate (POST) queries\n - support temporal queries\n - support pandas dataframe as a temporal query result\n - support subscriptions\n - find subscription conflicts\n - SubscriptionBuilder to help build subscriptions\n - auto-detect broker vendor and version\n - support follow relationships (chainable), e.g. `camera = parking.follow(\"availableSpotNumber.providedBy\")`\n\n## Getting started\n\n### Create our first parking Entity\n\nThe following code snippet builds the `OffstreetParking` sample entity from the ETSI documentation.\n\n```python\nfrom datetime import datetime\nfrom ngsildclient import Entity\n\nPARKING_CONTEXT = \"https://raw.githubusercontent.com/smart-data-models/dataModel.Parking/master/context.jsonld\"\n\ne = Entity(\"OffStreetParking\", \"Downtown1\")\ne.ctx.append(PARKING_CONTEXT)\ne.prop(\"name\", \"Downtown One\")\ne.prop(\"availableSpotNumber\", 121, observedat=datetime(2022, 10, 25, 8)).anchor()\ne.prop(\"reliability\", 0.7).rel(\"providedBy\", \"Camera:C1\").unanchor()\ne.prop(\"totalSpotNumber\", 200).loc(41.2, -8.5)\n```\n\nLet's print the JSON-LD payload.\n\n```python\ne.pprint()\n```\n\nThe result is available [here](https://github.com/Orange-OpenSource/python-ngsild-client/blob/master/parking_sample.jsonld).\u003cbr\u003e\n\n\n### Persist our parking in the Context Broker\n\nThe following example assumes that an Orion-LD context broker is running on localhost.\u003cbr\u003e\nA docker-compose config [file](https://raw.githubusercontent.com/Orange-OpenSource/python-ngsild-client/master/brokers/orionld/docker-compose-troe.yml) file is provided for that purpose.\n\n```python\nfrom ngsildclient import Client\n\nclient = Client(port=8026, port_temporal=8027)\nclient.create(e)\n```\n\n### Increase our parking occupancy as the day goes on\n\nEach hour ten more parkings spots are occupied, until 8 p.m.\n\n```python\nfrom datetime import timedelta\n\nprop = e[\"availableSpotNumber\"]\nfor _ in range(12):\n    prop.observedat += timedelta(hours=1)\n    prop.value -= 10\n    client.update(e)\n```\n\n### Retrieve our parking\n\nGet back our parking from the broker and display its `availableSpotNumber` property.\u003cbr\u003e\n\n```python\nparking = client.get(\"OffStreetParking:Downtown1\", ctx=PARKING_CONTEXT)\nparking[\"availableSpotNumber\"].pprint()\n```\n\nOnly one available parking spot remains at 8 p.m.\n\n```json\n{\n    \"type\": \"Property\",\n    \"value\": 1,\n    \"observedAt\": \"2022-10-25T20:00:00Z\",\n    \"reliability\": {\n        \"type\": \"Property\",\n        \"value\": 0.7\n    },\n    \"providedBy\": {\n        \"type\": \"Relationship\",\n        \"object\": \"urn:ngsi-ld:Camera:C1\"\n    }\n}\n```\n\n### Request the Temporal Representation of our parking\n\nFor convenience we retrieve it as a pandas dataframe.\n\n*If you don't have pandas installed, just omit the `as_dataframe` argument and get JSON instead.*\n\n```python\ndf = client.temporal.get(e, ctx=PARKING_CONTEXT, as_dataframe=True)\n```\n\nLet's display the three last rows.\n\n```python\ndf.tail(3)\n```\n\n|    | OffStreetParking   | observed                  |   availableSpotNumber |\n|---:|:-------------------|:--------------------------|----------------------:|\n| 10 | Downtown1          | 2022-10-25 18:00:00+00:00 |                    21 |\n| 11 | Downtown1          | 2022-10-25 19:00:00+00:00 |                    11 |\n| 12 | Downtown1          | 2022-10-25 20:00:00+00:00 |                     1 |\n\n### Let's throw in a more realistic parking management system\n\nLet us move from our first example to the more realistic parking example provided by the Smart Data Models Program.\n\n```python\nfrom ngsildclient import SmartDataModels\n\nparking = Entity.load(SmartDataModels.SmartCities.Parking.OffStreetParking)\n```\n\nOnce loaded we can manipulate our new parking the same way we've done until now.\u003cbr\u003e\nLet's see how it is occupied.\n\n```python\nn_total = parking[\"totalSpotNumber\"].value\nn_occupied = parking[\"occupiedSpotNumber\"].value\nn_avail= parking[\"availableSpotNumber\"].value\nprint(n_total, n_occupied, n_avail)\n```\n\nThis parking has 414 parking slots. 282 are occupied. 132 are available.\u003cbr\u003e\nIn order to complete our parking system we would like to add 414 spots to our datamodel.\u003cbr\u003e\nLet's create a reference parking spot to be used as a template.\n\n```python\nspot = Entity(\"ParkingSpot\", \"OffStreetParking:porto-ParkingLot-23889:000\")\nspot.prop(\"status\", \"free\")\nspot.rel(\"refParkingSite\", parking)\n```\n\nLet's clone this spot 414 times, assign a disctinct id to each one and occupy the 282 first spots.\u003cbr\u003e\nThis is a simplistic strategy but enough to keep the parking system consistent.\n\n```python\nspots = spot * n_total\nfor i, spot in enumerate(spots):\n    spot.id = f\"{spot.id[:-3]}{i+1:03}\"\n    if i \u003c n_occupied:\n        spot[\"status\"].value = \"occupied\"\n```\n\nWe now establish the relationship between the parking and its spots by adding a new attribute to the parking.\u003cbr\u003e\nHaving a mutual relationship is not necessarily needed. It depends on how we want to navigate in our datamodel. \u003cbr\u003e\nLet's do it for the sake of example.\n\n```python\nfrom ngsildclient import MultAttrValue\n\nmrel = MultAttrValue()\nfor spot in spots:\n    mrel.add(spot, datasetid=f\"Dataset:{spot.id[-26:]}\")\nparking.rel(\"refParkingSpot\", mrel)\n```\n\nTo sum up we have obtained 415 entities : 1 parking and 414 spots.\u003cbr\u003e\nMake a single list of these parts and save it into a file.\n\n```python\ndatamodel = sum(([parking], spots), [])  # flatten lists\nEntity.save_batch(datamodel, \"parking_system.jsonld\")\n```\nThe result is available [here](https://github.com/Orange-OpenSource/python-ngsild-client/blob/master/parking_system.jsonld).\u003cbr\u003e\nTime now to populate our parking system in the broker.\n\n```python\nclient.upsert(datamodel)\n```\n\nCheck everything is fine by asking the broker for the number of occupied spots.\u003cbr\u003e\nEventually close the client.\n\n```python\nclient.count(\"ParkingSpot\", q='refParkingSite==\"urn:ngsi-ld:OffStreetParking:porto-ParkingLot-23889\";status==\"occupied\"')  # 282\nclient.close()\n```\n\n### Let's go further\n\n1. Develop a NGSI-LD Agent\n\n    - Collect incoming data from parking IoT *(ground sensors, cameras)* and the parking system API\n    - Clean data, process data and convert to NGSI-LD entities\n    - Create and update entities into the NGSI-LD broker *in real-time*\n\n2. Subscribe to events\n\n    - Create a subscription to be informed when parking occupation exceeds 90%\n    - The software that listens to these highly-occupied parking entities can also be a NGSI-LD Agent\n\n    \u003cbr\u003eExample : programmatically subscribe to events\n\n    ```python\n    from ngsildclient import SubscriptionBuilder\n\n    subscr = SubscriptionBuilder(\"https://parkingsystem.example.com:8000/subscription/high-occupancy\")\n        .description(\"Notify me of high occupancy on parking porto-23889\")\n        .select_type(\"OffStreetParking\")\n        .watch([\"occupancy\"])\n        .query('occupancy\u003e0.9;controlledAsset==\"urn:ngsi-ld:OffStreetParking:porto-ParkingLot-23889\"')\n        .build()\n    client.subscriptions.create(subscr)\n    ```\n\n## Where to get it\n\nThe source code is currently hosted on GitHub at :\nhttps://github.com/Orange-OpenSource/python-ngsild-client\n\nBinary installer for the latest released version is available at the [Python\npackage index](https://pypi.org/project/ngsildclient).\n\n## Installation\n\n**ngsildclient** requires Python 3.9+.\n\n```sh\npip install ngsildclient\n```\n\n## Documentation\n\nUser guide is available on [Read the Docs](https://ngsildclient.readthedocs.io/en/latest/index.html).\n\nRefer to the [Cookbook](https://ngsildclient.readthedocs.io/en/latest/cookbook.html) chapter that provides many HOWTOs to :\n\n- develop various NGSI-LD Agents collecting data from heterogeneous datasources\n- forge NGSI-LD sample entities from the Smart Data Models initiative\n\n## License\n\n[Apache 2.0](LICENSE)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FOrange-OpenSource%2Fpython-ngsild-client","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FOrange-OpenSource%2Fpython-ngsild-client","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FOrange-OpenSource%2Fpython-ngsild-client/lists"}