An unofficial SmartThings websocket API library (alpha)

Overview

Smart Events

An unofficial SmartThings websocket API library (alpha)

Version Documentation Maintenance License: MIT Twitter: stephenmendez_ PayPal

💾 Installation

This is a Node.js module available through the npm registry.

$ npm i -S smart-events

🔌 Quick Start

const EventService = require('smart-events');

const st = new EventService();

// Initiate Connection
st.connect('<csrfToken>', '<cookie>');

// Connected via Websocket
st.on('connected', data => {
    console.log('Connected!', data);
    st.fetchUser(); // Fetch User Info
    st.fetchLocations(); // Fetch Hub Locations
    st.fetchRooms('<locationId>'); // Fetch Rooms @ Location
    st.fetchDevices('<locationId>'); // Fetch All Devices @ Location
    st.subscribe('<locationId>'); // Subscribe to Device Events @ Location
});

// Authenticated
st.on('authenticated', data => {
    console.log('Authenticated:', data)
});

// User Info
st.on('user', data => {
    console.log('User:', data);
});

// Hub Locations
st.on('locations', data => {
    console.log('Locations:', data);
});

// Rooms
st.on('rooms', data => {
    console.log('Rooms:', data);
});

// Devices
st.on('devices', data => {
    console.log('Devices:', data);
});

// Device Events
st.on('event', data => {
    console.log('Device Event:', data);
});

// Unknown message received
st.on('unknown', evt => {
    console.log('Unknown Event', evt);
});

// An API error occured
st.on('error', err => {
    console.log('An Error:', err);
});

🔮 Features

  • Asynchronous event driven API
  • Does not require long/short polling, webhook endpoints or a SmartApp
  • Detailed location, room, device and event information
  • Built in data validation (limited)
  • Easy integration into other projects (custom dashboards, automations, monitoring, logging, etc)

👓 Transparency

  • This is an early stage, alpha level project and may be unstable for some time

If you would like an official library, reach out to SmartThings / Samsung, mention this project & express your interest!

  • Should not be considered 'production ready' or used in critical implementations
  • Subject to unpredictable changes which can break this implementation without notice
  • Some security concerns & known vulnerabilities may exist and should be reviewed prior to using the package
  • Needs a refactor to align to best practices and OOP principles

🛠 Setup & Getting Started

Authentication

The current authentication approach has some security concerns which should be reviewed and acknowledged.

If anyone from SmartThings / Samsung reads this, please consider adding additional authentication schemes (OAuth, bearer token, etc) for better safety & usability.

The current implementation relies on a csrfToken & session cookie from the SmartThings Web App.

In order to get that information, the following steps must be performed in Google Chrome:

  1. Open the web browser and navigate to https://my.smartthings.com
  2. Enter your Samsung credentials to log into the web app
  3. Select the main location for which you plan on subscribing to events (it may be possible to monitor multiple locations but it has not been tested or documented)
  4. Open the Settings menu and enable Keep me signed in

Note, there is currently a bug in the UI which makes it appear as if the setting did not work (even though it did). You can confirm this worked later on via the authenticated event's output.

  1. Open the Developer Tools menu in Chrome and navigate to the Network tab
  2. Enable Preserve Log, select the WS filter and refresh the page
  3. Open the Console tab and copy/paste the following script to copy a JS object to your clipboard
copy({ 
  cookie: '',
  csrfToken: window._app.csrfToken,
  locationId: window.location.pathname.split('/')[2]
});
  1. Store the values somewhere secure & accessible by your code (see env.js or .env sections for general ideas)
  2. Open the Network tab, select the websocket request and under Headers right click the cookie and select Copy value
  3. Paste the value of the cookie somewhere secure & accessible by your code

env.js (optional)

This file may be created to store persistant environmental variables.

This file must be added .gitignore & never published. See security concerns for more details.

Example of storing information in this file:

module.exports = { 
  cookie: 'abc123',
  csrfToken: 'abc123',
  locationId: 'abc123'
}

Example of getting information from this file:

const {csrfToken, cookie, locationId} = require('./env.js');
console.log(csrfToken, cookie, locationId);

.env (optional)

This is a commonly used way to store persistant environmental variables.

In your code, you can use the dotenv package to access the stored values at runtime.

This file must be added .gitignore & never published. See security concerns for more details.

Example of storing information in this file:

CSRFTOKEN=abc123
COOKIE=abc123
LOCATIONID=abc123

Example of getting information from this file:

require('dotenv').config()
console.log(process.env.CSRFTOKEN, process.env.COOKIE, process.env.LOCATIONID);

💡 Methods

connect(csrfToken, cookie)

  • Initiates the websocket connection
  • csrfToken: string
  • cookie: string
  • Emits the connected event

fetchUser()

  • Requests information about the user
  • Emits the user event

fetchLocations()

  • Requests the list of locations available to the user
  • Emits the locations event

fetchRooms(locationId)

  • Requests the list of rooms at the specified location
  • locationId: string
  • Emits the rooms event

fetchDevices(locationId)

  • Requests the list of devices at the specified location
  • locationId: string
  • Emits the devices event

subscribe(locationId)

  • Subscribes to receive all device events at the location
  • It may be possible to subscribe to events from multiple locations but it has not been tested or documented
  • locationId: string
  • Emits the event event for all device updates

getUser(principal)

  • Retrieves the user object for the specified user from memory
  • principal: string

getLocation(locationId)

  • Retrieves the location object for the specified location from memory
  • locationId: string

getRoom(roomId)

  • Retrieves the room object for the specified room from memory
  • roomId: string

getDevice(deviceId)

  • Retrieves the device object for the specified device from memory
  • deviceId: string

🌐 Events

connected

  • The websocket connection has been opened
{
  sid: '<uuid>',
  upgrades: [],
  pingInterval: 25000,
  pingTimeout: 5000
}

authenticated

  • The server has authenticated the websocket connection
{
  userId: '<uuid>',
  sessionLength: 28800,
  stayLoggedIn: true // Can be used to confirm the "Authentication" step in the docs was performed correctly
}

user

  • Provides information about the user which is authenticated
  • Reminder, this information is likely sensitive and should not be shared
{
  principal: 'user_uuid:<uuid>',
  samsung_account_id: '<id>',
  countryCode: 'USA',
  user_name: 'user_uuid:<uuid>',
  scope: [ 'mobile' ],
  fullName: '<name>',
  access_tier: 0,
  exp: 1623210310, // Unix Timestamp
  uuid: '<uuid>',
  email: '<email>',
  authorities: [ 'ROLE_DEVELOPER', 'ROLE_USER' ],
  client_id: '<uuid>',
  impersonation: false, // Anyone know what this means?
  permissions: [
    'installedapp.read',
    'installedapp.edit',
    'scene.read',
    'scene.edit',
    'location.read',
    'location.edit',
    'event.read',
    'global.read',
    'global.edit',
    'error.read'
  ],
  featureFlags: {
    'cake.camera': true,
    'cake.customAuth': true,
    'cake.deviceRoomAssignment': true,
    'cake.feedbackLink': { hidden: true },
    'cake.languagePicker': false,
    'cake.cookiepolicy': true,
    'cake.debugview': false,
    'cake.nativeLogLevel': 'info'
  },
  session: { stayLoggedIn: true, sessionLength: 28800 }
}

location

  • To Be Determined

locations

  • Provides a list of locations attached to this account
[{
    locationId: '<uuid>',
    name: '<location name>',
    parent: { type: 'ACCOUNT', id: '<locationId of parent account>' }
  },
  ...
]

rooms

  • Provides a list of rooms at the location
[{
  roomId: '<uuid>',
  locationId: '<uuid>',
  name: '<room name>',
  backgroundImage: null,
  created: 1602298686032,
  lastModified: 1602298686032
},
  ...
]

devices

  • A list of all devices at the location
  • The full extent of possible values is unknown but there is a lot of data about each device
  • Some fields/values may be omitted in the following object for brevity
[
{
  locationId: '<uuid>',
  icon: 'https://client.smartthings.com/icons/oneui/x.com.st.d.sensor.multifunction',
  inactiveIcon: 'https://client.smartthings.com/icons/oneui/x.com.st.d.sensor.multifunction/off',
  plugin: { uri: 'wwst://com.samsung.one.plugin.stplugin' },
  lottieData: {
    icon: 'https://client-assets.smartthings.com/lottie/ic_device_multipurpose_sensor_1.json',
    scenes: []
  },
  deviceId: '<uuid>',
  roomId: '<uuid>',
  componentId: 'main',
  deviceName: '<Device Name>',
  deviceTypeData: { type: 'NONE' },
  states: [
    {
      capabilityId: 'contactSensor',
      attributeName: 'contact',
      componentId: 'main',
      value: 'open',
      label: 'Open',
      active: true,
      type: 'activated',
      icon: 'https://client.smartthings.com/icons/oneui/x.com.st.d.sensor.multifunction/on',
      arguments: []
    },
    {
      capabilityId: 'contactSensor',
      attributeName: 'contact',
      componentId: 'main',
      value: 'closed',
      label: 'Closed',
      active: false,
      type: 'inactivated',
      icon: 'https://client.smartthings.com/icons/oneui/x.com.st.d.sensor.multifunction/off',
      arguments: []
    },
    {
      capabilityId: '*',
      attributeName: '*',
      componentId: '*',
      value: '*',
      label: 'Connected',
      active: true,
      type: 'activated',
      icon: 'https://client.smartthings.com/icons/oneui/x.com.st.d.sensor.multifunction/on',
      arguments: []
    }
  ],
  actions: []
},
...
]

event

  • This is called when any device at the location issues an update
  • The stateChange field is used to determine if this is a new value or just a generic update/ping
  • This event handler is called many times so be mindful about how it is used
  • Some events for the same device will be fired in close succession based on similar attributes
  • The device object will only be populated if .getDevices('<locationId>') was previously called
    • This should be done if the device name is needed as it is not provided by the event itself
{
  event: {
    data: {
      eventType: 'DEVICE_EVENT',
      eventId: '<uuid>',
      locationId: '<uuid>',
      deviceId: '<uuid>',
      componentId: 'main',
      capability: 'powerMeter',
      attribute: 'power',
      value: 9.2, // Many devices will use a string value, such as 'on' for switches
      valueType: 'number', // Other types are possible
      unit: 'W',
      stateChange: true,
      time: '2021-06-09T04:16:03.854Z'
    },
    subscriptionId: '<long-uuid>'
  },
  device: {} // Same structure as previously defined

event::<deviceId>

  • Can be used to handle events generated from a specific device rather than all events
  • Provides the same object as the event handler

alert

  • To Be Determined

state

  • To Be Determined

control

  • To Be Determined

error

  • Error messages from the websocket API
  • It is unknown if there is any standardization of the format

unknown

  • This is called when any unrecognizable messages are received
  • Also provides a way to extend the capability of this library for currently unsupported messages

👤 Author

Stephen Mendez

🤝 Contributing

Contributions, issues and feature requests are welcome!
Feel free to check issues page. You can also take a look at the contributing guide.

😃 Show your support

Give a ⭐️ if this project helped you!

Consider making a donation of any amount!

PayPal

📝 License

Copyright © 2021 Stephen Mendez
This project is MIT licensed.


SmartThings is a registered trademark of SmartThings, Inc.

Samsung is a registered trademark of Samsung Electronics Co., Ltd.

Google Chrome is a registered trademark of Google LLC

Part of this README was generated with ❤️ by readme-md-generator

You might also like...

Alpha version of ALBot 2.0, the spiritual successor to ALBot

ALBot 2.0 Alpha Alpha version of ALBot 2.0, the spiritual successor to ALBot. ALBot 2.0 uses Discord.js to interface with the Discord API, supplanting

Nov 17, 2022

Team Alpha Super Awesome Cool Dynamite Wolf Squadron - 10 - Project 1

Team Alpha Super Awesome Cool Dynamite Wolf Squadron - 10 - Project 1

Super Hero Wiki This is a group project for our Interactive Front End Web Site. We created a Super Wiki that uses two (2) APIs to provide users a comi

Mar 24, 2022

🤖A Tic-Tac-Toe solver that uses the minimax algorithm and alpha-beta pruning to make it unbeatable

🤖A Tic-Tac-Toe solver that uses the minimax algorithm and alpha-beta pruning to make it unbeatable

Tic-Tac-Toe AI A Tic-Tac-Toe solver that uses the minimax algorithm and alpha-beta pruning to make it unbeatable How it Works Tic-Tac-Toe is what is k

May 20, 2022

NextJS BoilerPlate for Alpha version(Next.js + Styled Components + Customization + Theme)

This is a Next.js project bootstrapped with create-next-app. Getting Started First, run the development server: npm run dev # or yarn dev Open http://

Oct 24, 2022

A full documentation on everything we know about Alpha 1.0.16 versions.

Minecraft's Alpha 1.0.16 Versions Before you start, make sure to watch RetroGamingNow's video about this first. Highly influenced (technically a port

Dec 23, 2022

Use an HFS 2 'template' in HFS 3 - PRE-ALPHA stage

Tradit-TPL Use an HFS 2 'template' in HFS 3 - PRE-ALPHA stage Features Speed! Always response within 10ms then stream the page (without file sorting,

Jun 8, 2022

Script bot WhatsApp Md lanjutan dari R-TXZY Lawas Up Ke Versi Alpha Edition

R-TXZY-MD Jangan lupa kasih stars & follow :) https://botcahx-rest-api.herokuapp.com/ Join Group Diskusi NO BOT Install for termux termux-setup-stor

Jan 5, 2023

Script bot WhatsApp Md lanjutan dari R-TXZY Lawas Up Ke Versi Alpha Edition

Script bot WhatsApp Md lanjutan dari R-TXZY Lawas Up Ke Versi Alpha Edition

R-TXZY-MD Jangan lupa kasih stars & follow :) Information Dikarenakan WhatsApp Sekarang Update Jadi Tidak Ada List Menu Terpaksa Bot Ini Di Ganti Menu

Aug 14, 2022

ALPHA build of re621 2.0

ALPHA build of re621 2.0

RE621 is a comprehensive project created to improve the basic user experience while browsing e621.net. It consists of several different modules that e

Dec 16, 2022

Unofficial API client for the Tidbyt API. Use this client to control Tidbyt devices and integrate with other services.

Tidbyt Client for Node.js Unofficial API client for the Tidbyt API. Use this client to control Tidbyt devices and integrate with other services. Insta

Dec 17, 2022

An API 📦 for the the unofficial MyAnimeList API jikan.moe v4

An API 📦 for the the unofficial MyAnimeList API jikan.moe v4

Marika A promise based API wrapper for the unofficial MyAnimeList API Installation npm i @shineiichijo/marika yarn add @shineiichijo/marika 🚀 Import

Nov 4, 2022

A unofficial Node.js library for HoYoWiki API, can get the details of Genshin Impact items!

HoYoWiki API (Node.js Library) English | 繁體中文 | 简体中文 A unofficial Node.js library for HoYoWiki API, can get the details of Genshin Impact items! Repor

Jul 17, 2022

A Develop Tool to Test WebSocket, Socket.IO, Stomp, Bayeux, HTTP, TCP, UDP, WebRTC, DNS API.

A Develop Tool to Test WebSocket, Socket.IO, Stomp, Bayeux, HTTP, TCP, UDP, WebRTC, DNS API.

Sep 6, 2022

How to build a chat using Lambda + WebSocket + API Gateway? (nodejs)

How to build a chat using Lambda + WebSocket + API Gateway? (nodejs)

Description Source code for the lambda function from the screencast How to build a chat using Lambda + WebSocket + API Gateway? (nodejs) The reactjs c

Dec 28, 2022

Um bot feito utilizando a API baileys em WebSocket para o Whatsapp Multi-Devices.

Um bot feito utilizando a API baileys em WebSocket para o Whatsapp Multi-Devices.

Informação 📀 O BaileysBot foi feito utilzando a API Baileys Caso encontre algum BUG, faça um Novo Issue! Requisitos 📝 NodeJS Git Instalação 💾 Para

Dec 3, 2022

Unofficial API Documentation for the Axie Infinity's GraphQL Endpoint.

Axie GraphQL Documentation API Documentation for the Axie Infinity GraphQL Endpoint. Customization Guide This site is usings rocketseat. You may refer

Nov 24, 2022

Unofficial javascript wrapper to WhatsApp Cloud API.

heyooh Unofficial javascript wrapper to WhatsApp Cloud API. Its the javascript port for heyoo Features supported Sending messages Sending Media (image

Dec 30, 2022

An unofficial companion tool created for use alongside PhotoPrism to enable API endpoints and automation.

PhotoPrism Helper PhotoPrism Helper is an unofficial companion tool created for use alongside PhotoPrism. This project isn't associated with the Photo

Dec 25, 2022

An unofficial wrapper for the Bloxlink API using Node.js

Bloxlink API wrapper 🧬 Bloxlink-sdk is a simple, easy to use API wrapper for Bloxlinks API using Node.js. Anyone who can use code should be fairly co

Oct 21, 2022
Comments
  • Feedback & Ideas (0.0.0 - 1.0.0 | Alpha)

    Feedback & Ideas (0.0.0 - 1.0.0 | Alpha)

    Please share any comments on this issue or on the SmartThings forum!

    • Has this project helped you with your smart home project?
    • Is there something you would like to see improved?
    • Are you having difficulty with getting started?
    • Do you work at SmartThings and want to integrate this into the official SDK, reach out!
    opened by 401Unauthorized 0
Releases(v0.1.1)
Owner
Stephen Mendez
▫️Software Engineer @twitter Spaces ▫️M.S. Cybersecurity @ Fordham University
Stephen Mendez
NativeScript empowers you to access native api's from JavaScript directly. Angular, Vue, Svelte, React and you name it compatible.

NativeScript empowers you to access native APIs from JavaScript directly. The framework currently provides iOS and Android runtimes for rich mobile de

NativeScript 22k Jan 4, 2023
Lightweight MVC library for building JavaScript applications

Spine Spine is a lightweight MVC library for building JavaScript web applications. Spine gives you structure and then gets out of your way, allowing y

Spine JS Project 3.6k Jan 4, 2023
Super minimal MVC library

Espresso.js Espresso.js is a tiny MVC library inspired by Backbone and React with a focus on simplicity and speed. We've aimed to bring the ideas of u

TechLayer 534 Dec 11, 2022
Simple and elegant component-based UI library

Simple and elegant component-based UI library Custom components • Concise syntax • Simple API • Tiny Size Riot brings custom components to all modern

Riot.js 14.7k Jan 4, 2023
:fire: An extremely fast, React-like JavaScript library for building modern user interfaces

Inferno is an insanely fast, React-like library for building high-performance user interfaces on both the client and server. Description The main obje

Inferno 15.6k Jan 3, 2023
🙋‍♀️ 3kb library for tiny web apps

3kb library for tiny web apps. Sometimes, all you want to do is to try and do something—No boilerplate, bundlers, or complex build processes. Lucia ai

Aiden Bai 699 Dec 27, 2022
JavaScript UI library for data-driven web applications

Road to 2.0 The master branch has new, in-progress version of w2ui. You might want to consider 1.5 branch that is stable and supports older browsers.

Vitali Malinouski 2.4k Jan 3, 2023
Formily + SemiDesign: The Awesome Components Library with Formily & Semi

Formily + SemiDesign: The Awesome Components Library with Formily & Semi

Formily Organization 12 Dec 19, 2022
it is websocket-store for using easily websocket

Socket-Store It is Websocket Store How to use 1. Install # npm npm install socket-store # yarn yarn add socket-store 2. Create MessageHandler and

nerdchanii 4 Sep 13, 2022
This application provides the CDK project and a frontend that allows you to build a serverless chat application based on API Gateway's WebSocket-based API feature.

Serverless chat application using ApiGateway Websockets This project lets you provision a ready-to-use fully serverless real-time chat application usi

AWS Samples 60 Jan 3, 2023