Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Note

GraphQL API v1 is going to be deprecated in 2024Q3. If you plan to use GraphQL API, please, refer to the GraphQL Occupancy API V2

Table of Contents

GraphQL Occupancy API offers similar functionality to REST Occupancy API, however, there are additional benefits to using GraphQL.

You can select the fields you want to receive from the API. By requesting only the required fields from the API you can decrease traffic and consequently increase load speed.

Additionally, GraphQL Occupancy API supports subscriptions, which allows you to receive real-time occupancy updates.

Authorization

For details about authorization with GraphQL Occupancy API contact one of our team members.

Object & Field Descriptions

PositionOccupancy - describes a position and its occupancy state

  • id - position id

  • customId - user-defined id

  • groupId - position’s group id

  • occupancyStatus - parking space occupancy status

  • statusChangeTime - latest occupancy status change time

  • location - object containing latitude and longitude coordinates

    GroupOccupancy - describes a group, its positions and their occupancy states

  • id - group id

  • name - group user-defined name

  • customId - group user-defined id

  • location - object containing latitude and longitude coordinates

  • positionsOccupancy - list of all positions inside a group with its occupancy information

  • summary - group occupancy summary (total positions number, number of occupied and free positions)
  • SubscriptionArea - special object for describing occupancy states changes for some area

    • id - area id

    • location - object containing latitude and longitude coordinates

    • radius - area’s radius in meters

    • granularity - user-defined type for returned objects. User can decide between group occupancy information and position occupancy information

    • updates - list of GroupOccupancy or PositionOccupancy objects. Type of objects depends on the selected granularity option

    • updateTime - the time of last occupancy status update

  • Documentation

    The following GraphQL schema describes data types and operations that can be performed.

    Code Block
    languagegraphql
    enum OccupancyStatus {
      Occupied
      Free
    }
    
    type Location {
      lat: Float!
      lon: Float!
    }
    
    type PositionOccupancy {
      id: Int!
      customId: String
      groupId: Int
      occupancyStatus: OccupancyStatus
      statusChangeTime: AWSDateTime
      location: Location!
    }
    
    type OccupancySummary {
      total: Int!
      occupied: Int!
      available: Int!
      undefined: Int!
    }
    
    type GroupOccupancy {
      id: Int!
      name: String!
      customId: String
      location: Location
      positionsOccupancy: [PositionOccupancy]
      summary: OccupancySummary
    }
    
    union RtaUpdateObject = GroupOccupancy | PositionOccupancy
    
    
    enum SubscriptionGranularity {
      Position
      Group
    }
    
    type SubscriptionArea {
      id: Int!
      location: Location!
      radius: Int!
      granularity: SubscriptionGranularity!
      expiresOn: AWSDateTime!
      updates: [RtaUpdateObject]
      updateTime: AWSDateTime
    }
    
    
    type Query {
      groupOccupancy(id: Int!): GroupOccupancy
      findGroupOccupancies(
        ids: [Int]
        lat: Float
        lon: Float
        radius: Float
        levelId: Int
        floorNumber: Int
        zoneId: Int
        projectId: Int
        groupCustomId: String
        limit: Int = 50
        offset: Int
      ) : [GroupOccupancy]
      findPositionOccupancies(
        ids: [Int]
        lat: Float
        lon: Float
        radius: Float
        levelId: Int
        floorNumber: Int
        zoneId: Int
        projectId: Int
        groupCustomId: String
        limit: Int = 50
        offset: Int
      ) : [PositionOccupancy]
    }
    
    type Mutation {
      createSubscriptionArea(
        lat: Float, 
        lon: Float, 
        radius: Float, 
        granularity: SubscriptionGranularity
      ): SubscriptionArea
      updateSubscriptionArea(
        id: Int!, 
        lat: Float, 
        lon: Float, 
        radius: Float, 
        granularity: SubscriptionGranularity
      ): SubscriptionArea
    }
    
    type Subscription {
      onSubscriptionAreaUpdates(id: Int!): SubscriptionArea @aws_subscribe(mutations : ["pushPositionUpdates", "pushGroupUpdates"])
    }

    Operations

    The following operations can be performed using either Postman or curl command except for subscription operations.

    groupOccupancy

    This query will return the occupancy of a single group.

    Query

    Code Block
    languagegraphql
    query MyQuery { groupOccupancy(id: 123) { id customId name location { lat lon } positionsOccupancy { customId id groupId location { lat lon } occupancyStatus statusChangeTime

    In order to authorize with this API, you need to add the following header to your request:

    Key

    Value

    Authorization

    <your token>

    Your token can be obtained from the Company Info section of the Nwave’s console.

    Note

    You are able to call API not more frequent, than 300 times per 5 minutes interval with use of the same token. If amount of requests exceeds the limit, API reponds with error until the end of 5 minutes interval.

    GraphQL Schema

    The following GraphQL schema describes data types and operations that can be performed.

    Expand
    titleschema.graphql
    Code Block
    languagegraphql
    type GroupOccupancy @aws_api_key
    @aws_lambda {
    	id: ID!
    	zoneId: Int
    	levelId: Int
    	name: String!
    	groupType: String!
    	customId: String
    	location: Location
    	positionsOccupancy: [PositionOccupancy]
    	summary: OccupancySummary
    }
    
    input GroupOccupancyInput {
    	id: ID!
    	zoneId: Int
    	levelId: Int
    	name: String!
    	groupType: String!
    	customId: String
    	location: LocationInput!
    	positionsOccupancy: [PositionOccupancyInput!]!
    	summary: OccupancySummaryInput!
    }
    
    type LevelOccupancy @aws_api_key
    @aws_lambda {
    	id: Int
    	name: String
    	zoneId: Int!
    	floorNumber: Int
    	summary: OccupancySummary
    }
    
    input LevelOccupancyInput {
    	id: Int
    	zoneId: Int!
    	floorNumber: Int
    	name: String
    	summary: OccupancySummaryInput!
    }
    
    type Location @aws_api_key
    @aws_lambda {
    	lat: Float!
    	lon: Float!
    }
    
    input LocationInput {
    	lat: Float!
    	lon: Float!
    }
    
    enum OccupancyStatus {
    	Occupied
    	Free
    }
    
    type OccupancySummary @aws_api_key
    @aws_lambda {
    	total: Int!
    	occupied: Int!
    	available: Int!
    	undefined: Int!
    }
    
    input OccupancySummaryInput {
    	total: Int!
    	occupied: Int!
    	available: Int!
    	undefined: Int!
    }
    
    type PositionOccupancy @aws_api_key
    @aws_lambda {
    	id: ID!
    	customId: String
    	groupId: Int
    	occupancyStatus: OccupancyStatus
    	statusChangeTime: AWSDateTime
    	location: Location!
    	labels: [String]
    }
    
    input PositionOccupancyInput {
    	id: ID!
    	customId: String
    	groupId: Int!
    	occupancyStatus: OccupancyStatus!
    	statusChangeTime: AWSDateTime!
    	location: LocationInput!
    	labels: [String]
    }
    
    union RtaUpdateObject = ZoneOccupancy | LevelOccupancy | GroupOccupancy | PositionOccupancy 
    
    interface SubscriptionArea {
    	id: ID!
    	location: Location
    	radius: Int
    	zoneId: [Int]
    	levelId: [Int]
    	floorNumber: [Int]
    	groupId: [Int]
    	labels: [String]
    	granularity: SubscriptionGranularity!
    	expiresOn: AWSDateTime!
    }
    
    type SubscriptionAreaNoUpdates implements SubscriptionArea @aws_api_key
    @aws_lambda {
    	id: ID!
    	location: Location
    	radius: Int
    	zoneId: [Int]
    	levelId: [Int]
    	floorNumber: [Int]
    	groupId: [Int]
    	labels: [String]
    	granularity: SubscriptionGranularity!
    	expiresOn: AWSDateTime!
    }
    
    type SubscriptionAreaWithUpdates implements SubscriptionArea @aws_api_key
    @aws_lambda {
    	id: ID!
    	location: Location
    	radius: Int
    	zoneId: [Int]
    	levelId: [Int]
    	floorNumber: [Int]
    	groupId: [Int]
    	labels: [String]
    	granularity: SubscriptionGranularity!
    	expiresOn: AWSDateTime!
    	updates: [RtaUpdateObject]
    	updateTime: AWSDateTime
    }
    
    enum SubscriptionGranularity {
    	Position
    	Level
    	Group
    	Zone
    }
    
    type ZoneOccupancy @aws_api_key
    @aws_lambda {
    	id: ID!
    	name: String!
    	projectId: Int
    	summary: OccupancySummary
    }
    
    input ZoneOccupancyInput {
    	id: ID!
    	name: String!
    	projectId: Int
    	summary: OccupancySummaryInput!
    }
    
    type Mutation {
    	createSubscriptionArea(
    		lat: Float,
    		lon: Float,
    		radius: Int,
    		zoneId: [Int],
    		levelId: [Int],
    		floorNumber: [Int],
    		groupId: [Int],
    		labels: [String],
    		granularity: SubscriptionGranularity
    	): SubscriptionAreaNoUpdates
    		@aws_api_key
    @aws_lambda
    	updateSubscriptionArea(
    		id: ID!,
    		lat: Float,
    		lon: Float,
    		radius: Int,
    		zoneId: [Int],
    		levelId: [Int],
    		floorNumber: [Int],
    		groupId: [Int],
    		labels: [String],
    		granularity: SubscriptionGranularity
    	): SubscriptionAreaNoUpdates
    		@aws_api_key
    @aws_lambda
    	updatePositionOccupancy(positionId: Int!, occupancyStatus: OccupancyStatus!, timestamp: String!): PositionOccupancy
    		@aws_api_key
    	pushPositionUpdates(
    		id: ID!,
    		location: LocationInput,
    		radius: Int,
    		zoneId: [Int],
    		levelId: [Int],
    		floorNumber: [Int],
    		groupId: [Int],
    		labels: [String],
    		granularity: SubscriptionGranularity!,
    		expiresOn: AWSDateTime!,
    		updates: [PositionOccupancyInput!]!,
    		updateTime: String!
    	): SubscriptionAreaWithUpdates
    		@aws_api_key
    	pushGroupUpdates(
    		id: ID!,
    		location: LocationInput,
    		radius: Int,
    		zoneId: [Int],
    		levelId: [Int],
    		floorNumber: [Int],
    		groupId: [Int],
    		labels: [String],
    		granularity: SubscriptionGranularity!,
    		expiresOn: AWSDateTime!,
    		updates: [GroupOccupancyInput!]!,
    		updateTime: String!
    	): SubscriptionAreaWithUpdates
    		@aws_api_key
    	pushLevelUpdates(
    		id: ID!,
    		location: LocationInput,
    		radius: Int,
    		zoneId: [Int],
    		levelId: [Int],
    		floorNumber: [Int],
    		groupId: [Int],
    		labels: [String],
    		granularity: SubscriptionGranularity!,
    		expiresOn: AWSDateTime!,
    		updates: [LevelOccupancyInput!]!,
    		updateTime: String!
    	): SubscriptionAreaWithUpdates
    		@aws_api_key
    	pushZoneUpdates(
    		id: ID!,
    		location: LocationInput,
    		radius: Int,
    		zoneId: [Int],
    		levelId: [Int],
    		floorNumber: [Int],
    		groupId: [Int],
    		labels: [String],
    		granularity: SubscriptionGranularity!,
    		expiresOn: AWSDateTime!,
    		updates: [ZoneOccupancyInput!]!,
    		updateTime: String!
    	): SubscriptionAreaWithUpdates
    		@aws_api_key
    }
    
    type Query {
    	groupOccupancy(id: ID!): GroupOccupancy
    		@aws_api_key
    @aws_lambda
    	findGroupOccupancies(
    		ids: [Int],
    		lat: Float,
    		lon: Float,
    		radius: Int,
    		levelId: [Int!],
    		labels: [String!],
    		floorNumber: [Int!],
    		zoneId: [Int!],
    		projectId: Int,
    		groupCustomId: String,
    		limit: Int,
    		offset: Int
    	): [GroupOccupancy]
    		@aws_api_key
    @aws_lambda
    	findPositionOccupancies(
    		ids: [Int],
    		lat: Float,
    		lon: Float,
    		radius: Int,
    		groupId: [Int!],
    		levelId: [Int!],
    		labels: [String!],
    		floorNumber: [Int!],
    		zoneId: [Int!],
    		projectId: Int,
    		groupCustomId: String,
    		limit: Int,
    		offset: Int
    	): [PositionOccupancy]
    		@aws_api_key
    @aws_lambda
    }
    
    type Subscription {
    	onSubscriptionAreaUpdates(id: ID!): SubscriptionAreaWithUpdates
    		@aws_api_key
    @aws_lambda
    @aws_subscribe(mutations: ["pushPositionUpdates","pushGroupUpdates","pushLevelUpdates","pushZoneUpdates"])
    }
    
    # @api_key (admin) auth and @aws_lambda (user) auth are required for all types apart from:
    ##   updatePositionOccupancy
    ##   pushPositionUpdates
    ##   pushGroupUpdates
    ##   pushLevelUpdates
    ##   pushZoneUpdates
    ## These are for internal subscription notification and should have exclusive admin access
    schema {
    	query: Query
    	mutation: Mutation
    	subscription: Subscription
    }

    Subscription Areas

    A subscription area is an object that has two main functions:

    1. Filtering of the incoming position updates

    2. Defining the format of updates that is received by subscribers

    There are two types defined in the GraphQL schema for Subscription Areas:

    SubscriptionAreaNoUpdates - this type is returned when you create or update a Subscription Area. It does not have ‘updates’ & ‘updateTime’ fields as updates are only returned to active subscriptions.

    Info

    Subscription areas expiry 5 minutes after creation. Any update of a subscription area, including an empty one, will extend the expiration time by 5 minutes from the time of update.

    SubscriptionAreaWithUpdates - this type is returned to subscribers and as the name suggests it contains the ‘updates’ & ‘updateTime’ fields.

    Subscription Area Filters

    Subscription Areas filter the incoming updates and only notify the subscribers if the incoming position update matches all of the filters. Subscription Area filters can also be split into 2 categories:

    1. Hierarchical Filters: zoneId, groupId, levelId, floorNumber, labels

    2. Geospatial Filters: lat, lon, radius

    Info

    A valid subscription area must have at least one hierarchical filter and/or all of the geospatial filters.

    A match is when all position attributes are a subset (⊆) of the Subscription Area filters and it implies that a given position is inside a Subscription Area.

    Subscription Area filter with null value matches everything.

    The following example is a valid match between Subscription Area and Position Update.

    Position

    1. zoneId: 1

    2. groupId: 2

    3. levelId: 3

    4. floorNumber: 4

    5. labels: ['EV', ‘Disabled’]

    6. lat: 0.0

    7. lon: 0.0

    Subscription Area

    1. zoneId: [1, 2, 3]

    2. groupId: [1, 2, 3]

    3. levelId: [3]

    4. floorNumber: null

    5. lables: ['EV', ‘Disabled’, ‘VIP’]

    6. lat: 0.0

    7. lon: 0.0

    8. radius: 100

    Note

    Geospatial filters create a circular search area on the map, and there can be cases when a group of devices partially falls into the search area. (e.g. Half a group is within the search area and half is outside of the search area).

    Updates for positions that do not fall into the search area would still notify the subscribers.

    Subscription Area Updates

    The updates field of a Subscription Area can contain a list of 4 different types. All types within the updates list are the same. The type you will receive in the updates field depends on the granularity you choose.

    Granularity

    Updates Type

    Zone

    ZoneOccupancy

    Level

    LevelOccupancy

    Group

    GroupOccupancy

    Position

    PositionOccupancy

    Info

    Updates field will always contain only the object that has changed and therfore the list should always have a length of 1.

    Object & Field Descriptions

    SubscirptionArea

    • id - subscription area id

    • location - center coordinates of the search area

    • radius - radius from the center in meeters that creates the search area

    • zoneId - list of zone ids to match

    • levelId - list of level ids to match

    • floorNumber - list of floor numbers to match

    • groupId - list of group ids to match

    • labels - list of labels to match

    • granularity - defines the updates type

    • expiresOn - timestamp of subscription area expiration

    • udpates - occupancy updates for a subscription area

    • updateTime - timestamp of the occupancy update

    ZoneOccupancy

    • id - zone id

    • name - zone name

    • projectId - project id

    • summary - summary of occupancies in the Zone

    LevelOccupancy

    • id - level id

    • name - level name

    • zoneId - zone id

    • floorNumber - floor number of a level

    • summary - summary of occupancies on a Level

    GroupOccupancy

    • id - group id

    • zoneId - zone id

    • levelId - level id

    • name - group name

    • groupType - group type e.g. marked_bay

    • customId - user defined group id

    • location - сenter coordinates of a group

    • positionOccupancy - list of PositionOccupancy objects for a group

    • summary - summary of occupancies in the Group

    PositionOccupancy

    • id - position id

    • customId - custom id

    • groupId - group id

    • occupancyStatus - ‘occupied’, ‘free’ or null

    • statusChangeTime - timestamp of last occupancyStatus change

    • location: coordinates of a position

    Info

    The summary object should be used to display availability for all parking group types as it handles unmarked bay occupancies

    Operations

    The following operations can be performed using either Postman or curl command except for subscription operations.

    groupOccupancy

    This query will return the occupancy of a single group.

    Query

    Code Block
    languagegraphql
    query MyQuery {
      groupOccupancy(id: 123) {
        id
        customId
        name
        location {
          lat
          lon
        }
        positionsOccupancy {
          customId
          id
          groupId
          labels
          location {
            lat
            lon
          }
          occupancyStatus
          statusChangeTime
        }
      }
    }

    Response

    Code Block
    languagejson
    {
      "data": {
        "groupOccupancy": {
          "id": 3544,
          "customId": null,
          "name": "Foo",
          "location": {
            "lat": 51.493601937687224,
            "lon": -0.12852029611716095
          },
          "positionsOccupancy": [
            {
              "customId": "",
              "id": 1,
              "groupId": 123,
              "labels": null,
              "location": {
                "lat": 51.49360068522545,
                "lon": -0.1286061268139623
              },
              "occupancyStatus": "Free",
              "statusChangeTime": "2021-01-27T19:22:47.548+00:00"
            },
            {
              "customId": "",
              "id": 2,
              "groupId": 123,
              "labels": null,
              "location": {
                "lat": 51.493601937687224,
                "lon": -0.12852029611716098
              },
              "occupancyStatus": "Occupoed",
              "statusChangeTime": "2021-01-27T18:56:53.502+00:00"
            }
          ]
        }
      }
    }

    findGroupOccupancies

    This query will return a list of group occupancies.

    Query

    Code Block
    languagegraphql
    query MyQuery {
      findGroupOccupancies(ids: [1234]) {
        id
        location {
          lat
          lon
        }
        summary {
          available
          occupied
          total
          undefined
        }
      }
    }

     

    Response

    Code Block
    languagejson
    {
      "data": {
        "groupOccupancy": {
    
         "idfindGroupOccupancies": 3544,[
          {
    "customId": null,       "nameid": "Foo"1234,
            "location": {
              "lat": 5150.493601937687224780416909504915,
              "lon": -01.128520296117160950914407438684124
            },
            "positionsOccupancysummary": [
            {
              "customIdavailable": ""34,
              "idoccupied": 113,
              "groupIdtotal": 12347,
              "locationundefined": {0
                "lat": 51.49360068522545,}
          }
        ]
      "lon": -0.1286061268139623
          }
    }

    findPositionOccupancies

    This query will return a list of position occupancies.

    Query

    Code Block
    languagegraphql
    query MyQuery {
      findPositionOccupancies(ids: [1]) {
       }, id
        labels
        "occupancyStatus": "Free",location {
          lat
       "statusChangeTime": "2021-01-27T19:22:47.548+00:00"    lon
        },
        occupancyStatus
        statusChangeTime
    {    groupId
        customId
     "customId": "",
      }
    }

     

    Response

    Code Block
    languagejson
    {
      "data": {
        "findPositionOccupancies": [
          {
            "id": 212345,
     
            "groupIdlabels": 123["EV", "VIP"],
              "location": {
     
              "lat": 51.49360193768722449360068522545,
     
              "lon": -0.128520296117160981286061268139623
              },
     
            "occupancyStatus": "OccupoedFree",
     
            "statusChangeTime": "2021-01-27T1827T19:5622:5347.502548+00:00",
            }"groupId": 123,
            "customId": ""
     ]     }
        ]
      }
    }
    findGroupOccupancies

    createSubscriptionArea

    This query will return a list of group occupancies.

    Query

    mutation will create a new subscription area.

    Subscription Area Expiration

    By default, subscription areas expire 5 minutes after creation. Once a subscription area is expired, it cannot be extended and subscribers will stop receiving updates.

    Mutation

    Code Block
    languagegraphql
    querymutation MyQueryMyMutation {
      findGroupOccupanciescreateSubscriptionArea(ids:
    [1234]) {   granularity: Group, id
        location {
          lat
    lat: 51.493930, 
        lon: -0.129030, 
      }  radius: 100,
     summary {
          available
          occupied
          total
          undefined
      labels: ["EV"]
      ) }{
      } }

     

    Response

    Code Block
    languagejson
    {
      "data": {
        "findGroupOccupancies": [
     expiresOn
        granularity
        id
        location {
          lat
      "id": 1234,   lon
        }
    "location": {   radius
      }
    }
    

     

    Response

    Code Block
    languagejson
    {
      "latdata": 50.780416909504915,
       {
          "loncreateSubscriptionArea": -1.0914407438684124{
            }"expiresOn": "2021-01-28T23:20:06.232+00:00",
            "summarygranularity": {"Group",
              "availableid": 341,
     
            "occupiedlocation": 13,
     {
            "totallat": 4751.49393,
              "undefinedlon": -0.12903
          },
     }     "radius": 100
    }     ]}
      }
    }
    findPositionOccupancies

    onSubscriptionAreaUpdates

    This query will return a list of position occupancies.

    Query

    subscription will subscribe to occupancy updates inside an area.

    Selected updates object type must correspond to the granularity of the created search area:

    1. granularity: Position → updates { … on PositionOccupancy }

    2. granularity: Group → updates { … on GroupOccupancy }

    If you are unsure of the granularity for your subscription area, you can specify both types inside the updates.

    Subscription

    Code Block
    languagegraphql
    querysubscription MyQueryMySubscription {
      findPositionOccupanciesonSubscriptionAreaUpdates(idsid: [1]) {
        id
        locationexpiresOn
     {   granularity
       lat location {
        lon  lat
       }   lon
     occupancyStatus   }
     statusChangeTime   radius
     groupId   updateTime
     customId   }
    }

     

    Response

    Code Block
    languagejson
    updates {
      "data": {   ... on "findPositionOccupancies": [GroupOccupancy {
          {  id
          "id": 12345, name
           "location": {customId
            location {
    "lat": 51.49360068522545,         lat
     "lon": -0.1286061268139623        lon
    },        }
    "occupancyStatus": "Free",       positionsOccupancy {
    "statusChangeTime": "2021-01-27T19:22:47.548+00:00",         "groupId": 123,customId
             "customId": "" groupId
          }    id
    ]   }
    }

    createSubscriptionArea

    This mutation will create a new subscription area.

    Mutation

    Code Block
    languagegraphql
    mutation MyMutation {
      createSubscriptionArea(       location {
               granularity: Group,lat
         lat: 51.493930,      lon:
     -0.129030,      radius: 100  }
    ) {     expiresOn    occupancyStatus
    granularity     id     locationstatusChangeTime
    {       lat   labels
       lon     }
            summary {
          radius   } }
    

     

    Response

    Code Block
    languagejson
    {undefined
        "data": {     "createSubscriptionArea":total
    {       "expiresOn": "2021-01-28T23:20:06.232+00:00",  occupied
        "granularity": "Group",     available
     "id": 1,      }
    "location": {     }
       "lat": 51.49393, }
      }
      }
    

     

    Update

    Code Block
    languagejson
    {
      "londata": -0.12903{
          },"onSubscriptionAreaUpdates": {
          "radiusid": 1001,
        }   }
    }

    onSubscriptionAreaUpdates

    This subscription will subscribe to occupancy updates inside an area.

    Selected updates object type must correspond to the granularity of the created search area:

    1. granularity: Position → updates { … on PositionOccupancy }

    2. granularity: Group → updates { … on GroupOccupancy }

    If you are unsure of the granularity for your subscription area, you can specify both types inside the updates.

    Subscription

    Code Block
    languagegraphql
    subscription MySubscription {
      onSubscriptionAreaUpdates(id: 1) {
        id
        expiresOn
        granularity
        location {
          lat
          lon
        }
        radius
        updateTime
        updates {"expiresOn": "2021-01-28T23:20:06.232+00:00",
          "granularity": "Group",
          "location": {
            "lat": 51.49393,
            "lon": -0.12903
          },
          "radius": 1000,
          "updateTime": "2021-01-28T23:17:38.400+00:00",
          "updates": [
            {
              "id": 123,
            ... on GroupOccupancy {"name": "Foo",
            id  "customId": null,
         name     "location": {
      customId         location {
    "lat": 51.493601937687224,
             lat   "lon": -0.12852029611716095
          lon    },
        }      "positionsOccupancy": [
     positionsOccupancy {          {
    customId           groupId   "customId": "",
          id        "groupId": 123,
     location {             lat"id": 1,
                lon  "location": {
           }         "lat": 51.49360068522545,
    occupancyStatus           statusChangeTime     "lon": -0.1286061268139623
      }         summary {  },
            undefined      "occupancyStatus": "Occupied",
       total           occupied
    "statusChangeTime": "2021-01-28T23:17:38.400+00:00"
             available         }"labels": null
           }     }
      } } 

     

    Update

    Code Block
    languagejson
    {   "data": {  ],
      "onSubscriptionAreaUpdates": {       "idsummary": 1, {
                "expiresOnundefined": "2021-01-28T23:20:06.232+00:00",
     0,
        "granularity": "Group",       "locationtotal": 1,
       {         "latoccupied": 51.49393,1,
                "lonavailable": -0.12903 0
              },
            }
    "radius": 1000,      ]
      "updateTime": "2021-01-28T23:17:38.400+00:00",
     }
      }
      "updates": [
            }
    

    updateSubscriptionArea

    This mutation will update an existing subscription area.

    Info

    All subscription area updates will extend expiration by 5 minutes from the current time.

    You can also send empty mutation to only update the expiration.

    Mutation

    Code Block
    languagegraphql
    mutation MyMutation {
      updateSubscriptionArea(
           "id": 1231, 
             "name"granularity: "Foo"Position, 
             "customId": null,
              "location": {radius: 500
      ) {
        expiresOn
       "lat": 51.493601937687224, id
        granularity
        location {
     "lon": -0.12852029611716095    lat
          },lon
        }
        radius
    "positionsOccupancy": [ }
    }
    

     

    Code Block
    languagegraphql
    mutation ExtendSubscription {
      updateSubscriptionArea(
        {id: 1, 
      ) {
        expiresOn
       "customId": "", id
      }
    }
    

    Response

    Code Block
    languagejson
    {
      "data":  {
        "groupIdupdateSubscriptionArea": 123,{
          "expiresOn": "2021-01-28T23:20:06.232134+00:00",
          "id": 1,
          "granularity": "Position",
          "location": {
                    "lat": 51.49360068522545,
           49393,
            "lon": -0.128606126813962312903
          },
           },"radius": 500
        }
          }
    }

    Code Block
    languagejson
    {
      "

    occupancyStatus

    data": 

    "Occupied",

    {
        "updateSubscriptionArea": {
          

    "

    statusChangeTime

    expiresOn": "2021-01-28T23:

    17

    25:

    38

    06.

    400

    232134+00:00"

    } ]

    ,

    
          "

    summary

    id": 

    {

    1,
        }
      

    "undefined": 0,

    }
    }

    Use cases

    Query

    Use case

    Code Block
    languagegraphql
    query MyQuery {
      findGroupOccupancies(
        
    "total"
    lat: 
    1
    0.0, 
        lon: 0.0, 
        
    "occupied"
    radius: 2000
    
    1,
      ) {
        location {
       
    "available":
     
    0
      lat
          lon
     
    }
       }
        summary 
    }
    {
          
    ]
    available
        }
      }
    }

    updateSubscriptionArea

    This mutation will update an existing subscription area.

    Info

    All subscription area updates will extend expiration by 5 minutes from the current time.

    You can also send empty mutation to only update the expiration.

    Mutation
    
    }
    Info

    The summary object should be used to display availability for all parking group types

    Displaying all parking groups within 2km in a mobile app

    Image Added

    Code Block
    languagegraphql
    mutation
    query 
    MyMutation
    MyQuery {
      
    updateSubscriptionArea(
    findGroupOccupancies(zoneId: [1607]) {
        id
    : 1,
    
        name
        positionsOccupancy {
    
    granularity:
     
    Position,
         occupancyStatus
    
    radius:
     
    500
       
    )
     
    {
     labels
       
    expiresOn
     }
       
    id
     summary {
      
    granularity
        available
    
    location
     
    {
         occupied
     
    lat
         total
     
    lon
         
    }
    undefined
        
    radius
    }
      }
    }
     

    Getting group occupancy summary and each position status and labels to be able to calculate occupancy statistics by labels using only one query

    Code Block
    languagegraphql
    mutation
    query 
    ExtendSubscription
    MyQuery {
      
    updateSubscriptionArea
    groupOccupancy(
    id: 1
    ,
    ) {
        
    expiresOn
    positionsOccupancy {
       
    id
       
    } }

    Response

    Code Block
    languagejson
    location {
     
    "data":
      
    {
         
    "updateSubscriptionArea":
    lat
    
    {
           
    "expiresOn": "2021-01-28T23:20:06.232134+00:00",
     lon
          
    "id": 1,
    }
          occupancyStatus
    
    "granularity":
     
    "Position",
       }
      
    "location":
    }
    }

    Displaying individual parking positions when a user approaches his desired parking location

    Image Added
    Code Block
    languagegraphql
    query MyQuery {
      
    findPositionOccupancies(
        
    "
    lat
    "
    : 
    51
    0.
    49393
    0, 
        
    "
    lon
    "
    : 
    -
    0.
    12903 }
    0, 
        
    "
    radius
    "
    : 
    500
    2000,
        
    }
    labels: ['Disabled']
     
    } } Code Block
    languagejson
    { "data":
     ) {
        
    "updateSubscriptionArea":
    id
    
    {
        location {
     
    "expiresOn": "2021-01-28T23:25:06.232134+00:00",
         lat
        
    "id": 1,

    Query

    Use case
      lon
        }
        occupancyStatus
      }
    }

    Use cases

    Displaying occupancy statuses of positions with label “Disabled” within 2km radius

    Code Block
    languagegraphql
    query
    mutation 
    MyQuery
    MyMutation {
      
    findGroupOccupancies
    createSubscriptionArea(
        
    lat
    granularity: 
    0.0
    Position, 
        
    lon
    lat: 
    0
    1.
    0
    5, 
        
    radius
    lon: 
    2000
    1.5, 
     
    )
     
    {
      
    location { lat
    radius: 2000
      ) {
      
    lon
      id
      }
    }
    subscription MySubscription 
    summary
    {
      onSubscriptionAreaUpdates(
      id: 
    available
    <id from previous mutation>
     
    }
     )
    
    }
    }

    Displaying

    all

    live parking

    groups

    statuses within 2km

    in a mobile appImage Removed

    radius

    Code Block
    languagegraphql
    query
    mutation 
    MyQuery
    LevelOccuppancyMutation {
      
    groupOccupancy
    createSubscriptionArea(
    id:
    
     
    1)
     
    {
      zoneId: 3, 
    
    positionsOccupancy
     
    {
       granularity: Level
      
    location
    ) {
        id
      }
    
    lat
    }
    
    lon }
    subscription MySubscription {
      onSubscriptionAreaUpdates(
     
    occupancyStatus
     id: <id from previous 
    }
    mutation>
      
    }
    )
    }

    Displaying

    individual parking positions when a user approaches his desired parking locationImage Removed

    live occupancies per level in a zone (multistory car park)

    Image Added
    Code Block
    languagegraphql
    mutation 
    MyMutation
    LevelOccuppancyDisabledMutation {
      createSubscriptionArea(
        
    granularity
    zoneId: 
    Position
    3, 
        
    lat
    labels: 
    1.5
    "Disabled",
        
    lon
    granularity: 
    1.5, radius: 2000
    Level
      ) {
        id
      }
    }
    subscription MySubscription {
      onSubscriptionAreaUpdates(
      id: <id from previous mutation>
      )
    }

    Displaying live

    parking statuses within 2km radius

    occupancies of disabled spaces per level in a zone

    Image Added

    Code Block
    languagegraphql
    mutation MyMutation {
      updateSubscriptionArea(
        id: 1, 
      ) {
        expiresOn
        id
      }
    }

    Extend subscription area expiration

    Postman Collection

    Download Postman Collection here:

    View file
    nameGraphQL Occupancy.postman_collection.json

    Importing Collection

    1. Click import in My Workspace section.

    1. Upload the collection file and click

    Import.

    Adding API key to Postman Environment

    This collection uses the api_key variable to add an authorization token to the x-api-key header.

    1. To create a new environment click on the eye icon near the top right corner.

    2. Click Add to add a new environment.

    3. Add the gql_api_key variable name and your token in the initial value.

    4. Select the New Environment from the list.

    5. You can now test the requests in the GraphQL Occupancy Collection.

    Example Python Client

    There is a simple GraphQL client example in our Github repository. It is developed in Python and let you start getting data on demand and subscribe on occupancy change notifications.

    Please, follow the instructions in the README.md to prepare your invironment for running example.

    https://github.com/nwaveio/graphql_occupancy_example