Getting Started with Yonomi Platform

This Getting Started guide will walk you through using the platform to interact with a Schlage Encode lock. By the end of the walkthrough you should understand how to use Yonomi to interact with any type of device supported by Yonomi including lights, thermostats, smart garage doors, speakers, sensors and more.

1. Create a Yonomi Developer Playground Account

To get started, navigate to the Yonomi Developer Playground. The playground provides a web-based development environment for interacting with the Yonomi Platform.

If you have not already created an account, you’ll need to create a free Yonomi developer account to access the playground.

The Yonomi Developer Portal Playground - Not Logged In

Click the Login button in the top-right corner of the portal and follow the prompts to create your own developer account, then return to the Playground by clicking the Playground menu option in the left-side menu.

The Yonomi Developer Portal Playground - Logged In

The Playground includes an editor window area for entering your GraphQL Code (1), a button for executing code (2), an area for Yonomi Platform to send responses (3) and an area under the editor window for adding query variables (4). You may need to scroll the editor window to see the query variables section. You also see an area for exploring the Yonomi Platform GraphQL Schema (5) and a link to documentation (6)) in the top right corner of the response window.

Test out the health check call, which is already prepopulated in the editor window. Click the Play button to run the call.

πŸ“˜ New to GraphQL?

This guide presumes a basic understanding of HTTP POST method request/responses and uses GraphQL. If you’re not familiar with GraphQL, check out our Introduction to GraphQL for more information on the language.

Yonomi Platform Health Query

The Health object reflects general health state of the Yonomi platform. You’ll see results from Yonomi Platform that it’s up and ready for duty πŸ‘.

πŸ“˜ Why didn’t I have to login to use the Yonomi API?

The Yonomi Developer Playground uses your portal identification for authorization. In your development or production environments you’ll need to specify a JSON Web Token (JWT) authorization header in your HTTP request to identify the user on who’s behalf an API call is being made. More on User Authorization is covered here.

2. Query Available Integrations

Next we’ll look at available integrations. Yonomi establishes authorization to supported devices through an Integration object. An Integration represents a connection to the 3rd-party cloud which provides APIs to interact with the devices that 3rd party sells and supports. As an example, Yonomi supports an integration to the Schlage cloud, and Schlage uses their cloud to expose APIs used to interact with the locks they sell. The Integration object allows developers to create applications that let end-users programmatically establish an authorization link between their application user and their Schlage cloud account.

Yonomi Platform exposes one Integration per tenant for each supported cloud. As an example, there is one Integration object for Schlage, one for Ecobee and so on.

To query available Integrations paste the following query in the editor below the health query:

query getAllIntegrations {
  integrations {
    edges {
      node {
        id
        displayName
      }
    }
  }
}

Querying Integrations

Click the Play button and select getAllIntegrations from the dropdown that appears under the button to execute the GraphQL query.

Querying Integrations

The response is a list of all available integrations on Yonomi Platform. Note this list includes a linkedAccount object for Schlage, which we’ll use below.

πŸ“˜ More on Integrations, LinkedAccounts and Devices

Working with the Integration object is the starting point for adding and authorizing LinkedAccounts and Devices to a user’s account. You can think of a LinkedAccount as an established, authorized link between a specific user and a 3rd-party cloud account. The LinkedAccount allows that user to interact with one or more devices registered to that 3rd-party account.

Integrations are used to add a LinkedAccount to a user’s account, and LinkedAccounts are used to access Devices.

Here’s how the process works with the starting point of a user having already logged into your app:

  1. A query is made from your app/application to Yonomi Platform to obtain an account linking URL. An account linking URL is used to establish the authorization link. The query will pass the ID of the Integration object to which authorization will be established. Yonomi Platform will return the URL in the response back to the app.

  2. The app/application redirects the user to the account linking URL (via sandboxed webview or other sufficiently secure method for loading sensitive URLs)

  3. The redirect will resolve and send the user to the authorization site the 3rd-party device provider has set up to complete OAuth2.0 authorization. The user will log in with the username and password for their 3rd-party account.

  4. After successful login, the 3rd-party site will inform the user they are granting Yonomi/Your company access to interact with and control devices. The user will click a button to acknowledge and confirm their decision to authorize.

  5. The 3rd-party site will redirect the user back to Yonomi Platform with granted permissions to access and control devices. At this step, Yonomi will create a linkedAccount object and one or more device objects representing the devices that have just been authorized to be used via the 3rd-party API. These objects are added to the user account and now accessible via GraphQL API.

  6. Yonomi Platform will display a success message back to the user. If a Callback URL is set for the tenant then the user will be redirected back to the app/application instead. Yonomi supports a success callback and a fail/error callback per tenant. If you’d like to set callback URLs for your user experience just have one available contact Yonomi Customer Success to have it set.

Diagram of the user authorization flow

These steps all take place over the course of a few seconds to a minute, mostly depending on how long it takes the user to log in to their 3rd-party account.

3. Obtain an Account Linking URL

Next, we’ll make a call to obtain the account linking URL for a Schlage account and authorize the Schlage account to be used with Yonomi Platform. Identify the Integration ID for the Schlage Integration object from results of the previous call. We’ll populate this value as a query variable.

Add the following mutation to the editor:

mutation generateAccountLinkingUrl ($integrationId: ID!) {
  generateAccountLinkingUrl(integrationId: $integrationId) {
    url
    expiresAt
    integration {
      id
      displayName
    }
  }
}

Notice this mutation uses a query variable called integrationId that we’ll need to populate. Scroll down to the Query Variables area at the bottom of the Editor window area. You may need to grab and drag the Query variable pane up to access it. Once accessible, paste the following:

{
  "integrationId": "replaceWithIntegrationID"
}

Setting the Integration ID Query Variable

Copy the Integration ID of the Schlage Integration object from the previous call and paste it as the value of the integrationId variable, replacing the existing value (replaceWithIntegrationID):

Setting the Integration ID Query Variable

Click the Play button and select the generateAccountLinkingUrl mutation to run that call. The response will be a payload that includes a long URL – this is the Account Linking URL for a Schlage account.

Schlage Account Linking URL

4. Authorizing a Linked Account

Next, we’ll authorize a Schlage account. Copy the URL, paste it into a new browser tab and run it.

🚧 Work Fast - You Only Have 2 Minutes

The token used in this request has an expiration timeframe of only 120 seconds, so you’ll need to work fast at this step, copying the URL and pasting it into a browser within 2 minutes. You’ll know you didn’t get this done fast enough if the loading the URL yields an error instead of a 3rd-party login page. If you’ve run longer than 2 minutes, just make a call generate a new URL and try again.

You should see the browser load a page with instruction to log in to your Schlage account. (For Schlage, the user/pass challenge screen is prefaced by an agreement screen you must acknowledge before you get to the screen where you can enter your Schlage account credentials.) Also notice here that the browser URL shows you have been redirected to a Schlage site, not a Yonomi site. This is the redirect mentioned in step 3 of the flow above.

Schlage OAuth Authorization Screens

❗️ Important: Use Restrictive Views to Secure the 3rd-party Cloud Authorization (OAuth) Process

Yonomi supports APIs for adding and managing 3rd-party authorizations from directly within your mobile app/application. Yonomi provides a way for structuring an authenticated web URL that, when launched in a user’s client browser, loads the relevant 3rd-party login/authorization page to complete the OAuth process.

While testing, using a standard browser is fine to test your process. In production, as a best practice design pattern for this process, it is important that your mobile application avoid use of in-app webviews when loading this URL. In-app webviews used in this process violate trust with the user/client. Your mobile application should use Safari Webviews or sandboxed Chrome Custom Tabs (or similar mobile browser sandbox tab feature) when loading this URL. Don’t worry about a disconnected user experience; Yonomi allows you to set an app callback URL upon completion of the process so your users will redirect right back into your app/designed experience.

Developers should design fallbacks to a full browser experience in their application if those mobile browser features are not available. Yonomi may block the use of in-app webviews within your application for this feature in the future so it’s important that they not be used.

Reach out to Yonomi Customer Success if you need guidance on this step.

Enter your Schlage account details and click the Sign In button to log in. Schlage will process your request and forward you back to Yonomi, where you’ll be greeted either with a Success message, or if you’ve established a Callback URL for your application, you’ll be redirected to the callback URL so your application can pick up the process.

Authorization Success Page

🚧 What if I need to add multiple accounts to a single user account? Is that possible?

Yes. You can link multiple accounts of the same brand and integration type to any one or more Yonomi Platform users. As an example, if you have multiple Schlage accounts managing multiple locks, you can link one or more of those Schlage accounts to a single Yonomi account or link the locks to two different Yonomi user accounts. The Yonomi Customer Success team can provide guidance on best practices for your needs.

At this point, a LinkedAccount and one or more Device objects have been added to the user’s Yonomi Platform account.

Reviewing the Linked Account

To view the newly added Schlage Linked Account, paste and run the following query:

query getLinkedAccounts {
  me {
    id
    lastActivityAt
    firstActivityAt
    linkedAccounts {
      edges {
        node {
          id
          status
          createdAt
          integration {
            id
            displayName
          }
        }
      }
    }
  }
}

If you’ve successfully linked the Schlage account you’ll see account details in the response window.

Linked Accounts Query

5. Viewing Devices

When the LinkedAccount was authorized and added, any devices associated with that account were also added.

To see available the devices, paste and run the following query:

query getMyDevices {
  me {
    devices {
      pageInfo {
        hasNextPage
      }
      edges {
        node {
          id
          displayName
          productInformation {
            description
            manufacturer
            model
            serialNumber
          }
          traits {
            name
            instance
            ... on BatteryLevelDeviceTrait {
              state {
                percentage {
                  reported {
                    value
                    sampledAt
                    createdAt
                  }
                  desired {
                    value
                    delta
                    updatedAt
                  }
                }
              }
            }
            ... on LockDeviceTrait {
              properties {
                supportsIsJammed
              }
              state {
                isLocked {
                  reported {
                    value
                    sampledAt
                    createdAt
                  }
                  desired {
                    value
                    delta
                    updatedAt
                  }
                }
              }
            }
            ... on PinCodeCredentialDeviceTrait {
              state {
                pinCodeCredentials {
                  reported {
                    value {
                      pageInfo {
                        hasNextPage
                      }
                      edges {
                        node {
                          name
                          pinCode
                          schedules
                        }
                      }
                    }
                    createdAt
                    sampledAt
                  }
                  desired {
                    value {
                      pageInfo {
                        hasNextPage
                      }
                      edges {
                        node {
                          name
                          pinCode
                          schedules
                        }
                      }
                    }
                    delta {
                      pageInfo {
                        hasNextPage
                      }
                      edges {
                        node {
                          name
                          pinCode
                          schedules
                        }
                      }
                    }
                    updatedAt
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}

This query returns a detailed payload of all details for available devices on the account. Note that if you have multiple devices you’ll see details of all added devices in the response window. If you’ve authorized any other linkedAccounts, devices for those accounts would show up here as well.

Devices Query

Notice the Device ID in the response – we’ll need to use this for the next step. You’ll find the device ID as the first id variable under each node object in the response.

6. Running Device Actions – Locking and Unlocking a Door

We’re now ready to control our lock device. We’ll start by locking it. Be sure your lock is physically in the unlocked position before starting.

Paste the following mutation in the editor:

mutation makeLockActionRequest ($deviceId: ID!) {
	actionLockSetLocked (deviceId: $deviceId lock: true) {
    actionId
    device {
 	    traits {
       name instance
       ... on LockDeviceTrait {
         properties { supportsIsJammed }
         state {
          isLocked {
            reported { value sampledAt createdAt }
            desired { value delta updatedAt }
            }
          }
        }
      }
    }
  }
}

Next, copy your Device ID from the response of the devices query call above.

Open the Query Variables pop-up window and add the following variable, replacing replaceWithDeviceID with your copied Device ID:

  "deviceId": "replaceWithDeviceID"

πŸ‘ Be sure to include a comma between variable definitions

Setting the Device ID Query Variable

Click the play button and select the makeLockActionRequest mutation from the list to execute it. Your lock should change from unlocked to locked state.

Let’s look at the response to this mutation, specifically at the state element, which is inside the traits object in the response.

Make Lock Action Response

The state element returns details about the state of the lock – specifically whether it is currently in the locked or unlocked state, as well as the desired state change requested. In this case the lock reports its current state as unlocked (false), with a desired state of locked (true). It’s important to note that this response does not indicate that the lock was successfully locked – it only indicates a request to perform the action was successfully made to the 3rd-party cloud.

If you are near the lock you are controlling you likely saw/heard the lock actuate and beep. If you are not near the lock, you can look up the state of your request by looking at the device’s most recent events.

The response also included an actionId – the Action ID can be used to look up the result of the action to confirm the requested was successfully completed. There are two ways to look up the status of an action.

One way is to review the most recent events associated with the device (see the Events tab in GraphQL Playground), correlating the actionId for the most recent events, then checking the status attribute for a value of RESOLVED.

Another way is to begin to capture webhook events by providing Yonomi Customer Success with your webhook endpoint. More on webhooks in the Getting Started with Webhooks Guide

Next, we’ll unlock the door. Copy the makeLockActionRequest and paste it, then change the name to makeUnlockActionRequest Modify the lock parameter value from true to false and run the mutation.

Make UnLock Action Response

The lock should unlock.

Congratulations – you’ve just completed the getting started walkthrough for Yonomi Platform. From here it will be helpful to explore the Device Traits, Device Events, Webhooks.

More on the Explorer and Documentation

Yonomi Developer Playground includes two sections of built-in documentation:

Docs : The Docs section covers descriptive documentation of all queries and mutations available in the Yonomi Platform. The docs tab includes a search box where you can search for any object, or alternatively you can browse the docs manually. Each object includes breadcrumb-style link navigation to allow you to drill into object details and referenced objects. You might think of the Docs tab as a descriptive version of the GraphQL Schema.

Explorer : The Explorer section brings up the Yonomi Platform GraphQL schema. The GraphQL schema is a structured representation of the data that clients can request from a GraphQL API. It also defines the queries and mutation functions that clients can use to read and write data from a GraphQL server. All client or application UI data requirements are defined in the GraphQL schema.

πŸ‘ More on the importance of the GraphQL Schema

The schema is a foundational component of a GraphQL implementation as they enable automatic code generation, validation and parsing, introspection, and type safety for an API. In the same way that strong typing provide structure for writing code in programming languages, the GraphQL schema defines valid inputs and structure for queries written in the Playground. If you noticed auto-code completion and suggestions by the editor when typing in the Editor window, this is possible because the schema defines what objects and queries can be used and how they should be constructed. The schema is also what makes it possible for the Playground to catch errors in real time while you are writing your code and governs what the GraphQL engine will consider valid at runtime.

The GraphQL schema enables decoupling of the client from the backend and allows applications to evolve and scale independently.

The Yonomi Platform is the easiest way to integrate with connected home products to build residential IoT solutions. Yonomi provides a platform that allows you to easily integrate to a large ecosystem of popular residential smart home products, allowing you to both control and receive data from Consumer IoT devices directly from within your solution.