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

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!
}

typeenum MutationOccupancyStatus {
	createSubscriptionArea(Occupied
		lat: Float,
		lon: Float,
		radius: Int,
		zoneId: [Int],
		levelId: [Int],
		floorNumber: [Int],
		groupId: [Int],
		labels: [String],
		granularity: SubscriptionGranularity
	): SubscriptionAreaNoUpdates
		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 	updateSubscriptionArea({
		id: ID!,
		latcustomId: Float,String
		longroupId: Float,Int
		radiusoccupancyStatus: Int,OccupancyStatus
		zoneIdstatusChangeTime: [Int],AWSDateTime
		levelIdlocation: [Int],Location!
		floorNumberlabels: [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,
		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!,
		updates: [PositionOccupancyInput!]!,
		updateTime: String!
	): SubscriptionAreaWithUpdates
		}

type SubscriptionAreaNoUpdates implements SubscriptionArea @aws_api_key
	pushGroupUpdates(@aws_lambda {
		id: ID!,
		location: LocationInput,Location
		radius: Int,
		zoneId: [Int],
		levelId: [Int],
		floorNumber: [Int],
		groupId: [Int],
		labels: [String],
		granularity: SubscriptionGranularity!,
		expiresOn: AWSDateTime!,
		updates: [GroupOccupancyInput!]!,
		updateTime: String!
	): SubscriptionAreaWithUpdates
		}

type SubscriptionAreaWithUpdates implements SubscriptionArea @aws_api_key
	pushLevelUpdates(
@aws_lambda {
		id: ID!,
		location: LocationInput,Location
		radius: Int,
		zoneId: [Int],
		levelId: [Int],
		floorNumber: [Int],
		groupId: [Int],
		labels: [String],
		granularity: SubscriptionGranularity!,
		expiresOn: AWSDateTime!,
		updates: [LevelOccupancyInput!RtaUpdateObject]!,
		updateTime: String!AWSDateTime
}

enum SubscriptionGranularity {
	):Position
SubscriptionAreaWithUpdates	Level
	Group
	Zone
}

type ZoneOccupancy @aws_api_key
	pushZoneUpdates(
	@aws_lambda {
	id: ID!,
		location: LocationInputname: 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!,
		expiresOn): AWSDateTime!,SubscriptionAreaNoUpdates
		updates: [ZoneOccupancyInput!]!,@aws_api_key
@aws_lambda
	updateSubscriptionArea(
		updateTimeid: StringID!,
		)lat: SubscriptionAreaWithUpdatesFloat,
		@aws_api_key
}

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 {
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!,
		customIdlocation: StringLocationInput,
	groupId	radius: Int,
	occupancyStatus	zoneId: OccupancyStatus[Int],
		statusChangeTimelevelId: AWSDateTime[Int],
		locationfloorNumber: Location!
}

input PositionOccupancyInput {
	id: ID!
	customId: String
	groupId: Int!
	occupancyStatus: OccupancyStatus!
	statusChangeTime: AWSDateTime!
	location: LocationInput!
}

type Query {
	groupOccupancy(id: ID!): GroupOccupancy
		@aws_api_key
@aws_lambda
	findGroupOccupancies(
		ids: [Int],
		lat: Float,
		lon: Float,
		radius: Int[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!],
		zoneIdgroupId: [Int!],
		labels: [String],
		projectIdgranularity: IntSubscriptionGranularity!,
		groupCustomIdexpiresOn: StringAWSDateTime!,
		limitupdates: Int[GroupOccupancyInput!]!,
		offsetupdateTime: IntString!
	): [GroupOccupancy]SubscriptionAreaWithUpdates
		@aws_api_key
@aws_lambda
	findPositionOccupancies	pushLevelUpdates(
		idsid: [Int]ID!,
		latlocation: FloatLocationInput,
		lonradius: FloatInt,
		radiuszoneId: [Int],
		groupIdlevelId: [Int!],
		levelIdfloorNumber: [Int!],
		floorNumbergroupId: [Int!],
		zoneIdlabels: [Int!String],
		projectIdgranularity: IntSubscriptionGranularity!,
		groupCustomIdexpiresOn: StringAWSDateTime!,
		limitupdates: Int[LevelOccupancyInput!]!,
		offsetupdateTime: IntString!
	): [PositionOccupancy]SubscriptionAreaWithUpdates
		@aws_api_key
@aws_lambda
}

union RtaUpdateObject = ZoneOccupancy | LevelOccupancy | GroupOccupancy | PositionOccupancy 

type Subscription {
	onSubscriptionAreaUpdates(id: ID!): SubscriptionAreaWithUpdates
		@aws_api_key
@aws_lambda
@aws_subscribe(mutations: ["pushPositionUpdates","pushGroupUpdates","pushLevelUpdates","pushZoneUpdates"])
}

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 	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!
	location): LocationSubscriptionAreaWithUpdates
	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!
}

# @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
	@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

query MyQuery { groupOccupancy(id: 123) { id customId name location {
Code Block
languagegraphql
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"
        lat}
      lon]
    }
  }
 positionsOccupancy}

findGroupOccupancies

This query will return a list of group occupancies.

Query

Code Block
languagegraphql
query MyQuery {
  findGroupOccupancies(ids: [1234]) {
  customId  id
    idlocation {
     groupId lat
     location {lon
    }
   lat summary {
      lonavailable
      }occupied
      occupancyStatustotal
      statusChangeTimeundefined
    }
  }
}

 

Response

Code Block
languagejson
{
  "data": {
    "groupOccupancyfindGroupOccupancies": {[
      {
"id": 3544,       "customIdid": null1234,
   
  "name": "Foo",       "location": {
          "lat": 5150.493601937687224780416909504915,
          "lon": -01.128520296117160950914407438684124
        },
        "positionsOccupancysummary": {
  [         {"available": 34,
          "customIdoccupied": ""13,
          "idtotal": 147,
          "groupIdundefined": 123,0
        }
 "location": {    }
    ]
   "lat": 51.49360068522545,
  }
}

findPositionOccupancies

This query will return a list of position occupancies.

Query

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

 

Response

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

findGroupOccupancies

This query will return a list of group occupancies.

Query

Code Block
languagegraphql
query MyQuery {,
  findGroupOccupancies(ids: [1234]) {     id"groupId": 123,
    location {   "customId": ""
  lat    }
  lon  ]
  }
    summary}

createSubscriptionArea

This 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
mutation MyMutation {
  createSubscriptionArea(
   available granularity: Group, 
   occupied lat: 51.493930, 
   total lon: -0.129030, 
   undefined radius: 100,
  }   }
}

 

Response

Code Block
languagejson
{
  "data": {
    "findGroupOccupancies": [
      labels: ["EV"]
  ) {
    expiresOn
   "id": 1234, granularity
        "location": {id
    location {
      "lat":
50.780416909504915,      lon
    "lon": -1.0914407438684124}
    radius
  }
 },}

 

Response

Code Block
languagejson
{
  "data": {
    "summarycreateSubscriptionArea": {
      "expiresOn": "2021-01-28T23:20:06.232+00:00",
      "availablegranularity": 34"Group",
      "id": 1,
      "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
    }
    occupancyStatus
    statusChangeTime
    groupId
    customId
  }
}

 

Response

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

createSubscriptionArea

This 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
mutation MyMutation {
  createSubscriptionArea(customId
          granularity:groupId
Group,      lat: 51.493930,   id
  lon: -0.129030,      radius: 100location {
 ) {     expiresOn     granularitylat
    id     location {  lon
    lat      }
lon     }     radiusoccupancyStatus
  } } 

 

Response

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

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

      }
    }
  }
}

 

Update

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

 

Update

Code Block
languagejson
{   "dataoccupancyStatus": {
    "onSubscriptionAreaUpdates": {"Occupied",
      "id": 1,       "expiresOnstatusChangeTime": "2021-01-28T23:2017:0638.232400+00:00",
      "granularity": "Group",       "locationlabels": null
{         "lat": 51.49393,  }
      "lon": -0.12903   ],
   },       "radiussummary": 1000,{
      "updateTime": "2021-01-28T23:17:38.400+00:00",       "updatesundefined": [
       0,
 {           "idtotal": 1231,
            "nameoccupied": "Foo"1,
            "customIdavailable": null,0
          "location":}
{        }
    "lat": 51.493601937687224, ]
    }
  }
   "lon": -0.12852029611716095
    }

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: }1, 
         "positionsOccupancy"granularity: [Position, 
    radius: 500
  ) {
 {   expiresOn
    id
    granularity
 "customId": "",  location {
      lat
    "groupId": 123, lon
    }
    radius
  }
"id": 1,
 }

 

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

Response

Code Block
languagejson
{
  "latdata": 51.49360068522545,{
    "updateSubscriptionArea":  {
         "lonexpiresOn": -0.1286061268139623"2021-01-28T23:20:06.232134+00:00",
      "id": 1,
      }"granularity": "Position",
          "location": {
   "occupancyStatus": "Occupied",     "lat": 51.49393,
        "statusChangeTimelon": "2021-01-28T23:17:38.400+00:00"-0.12903
      },
     } "radius": 500
    }
   ],}
}

Code Block
languagejson
{
  "data": 

{
    

"

summary

updateSubscriptionArea": {
    

  "expiresOn": "2021-01-28T23:25:06.232134+00:00",
      "

undefined

id": 

0,

1,
    }
  }
}

Use cases

Query

Use case

Code Block
languagegraphql
query MyQuery {
  findGroupOccupancies(
    
"total"
lat: 
1
0.0, 
    lon: 0.0, 
    
"occupied"
radius: 
1,
2000
  ) {
    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,
 id
    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 id } }

Response

Code Block
languagejson
{ "data": {
positionsOccupancy {
      location {
        
"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: 
}
2000,
    
"radius"
labels: 
500
['Disabled']
  ) {
}
   
} } Code Block
languagejson
{ "data": {
 id
    location 
"updateSubscriptionArea":
{
   
"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(
    granularity: Position, 
    lat: 
0
1.
0
5, 
    lon: 
0
1.
0
5, 
    radius: 2000
  ) {
    
location { lat lon } summary
id
  }
}
subscription MySubscription {
  onSubscriptionAreaUpdates(
  id: 
available
<id from previous mutation>
 
}
 )
}
} InfoThe summary object should be used to display availability for all parking group types

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
 ) {
lat

 
lon
   id
  }
}
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,
Level
  
radius: 2000
) {
    id
  }
}
subscription MySubscription {
  onSubscriptionAreaUpdates(
  id: <id from previous mutation>
 
) }Displaying live parking statuses within 2km radius
 )
}

Displaying live 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