Smartthings CLI - Create Virtual Device

I promise I have searched a bit.

What’s the story around the Virtual Device created by the CLI? It does not seem to be a local device. Are there any plans for the engineering team to do anything with this? Is this what our groovy old style virtual devices will be migraated to?

Hi, @Davec!

More information about virtual devices will be shared later on. We understand there are some questions around this and, we have shared them with the team.
We’ll keep you updated, please bear with us :smiley:

2 Likes

@nayelyz With a virtual presence sensor created with the CLI, can you change the value of the device (present/not present) via a http post? As is the presenceSensor capability doesn’t accept commands but I’d its a virtual what will cause the state change?

I can probably help here.

Do a POST to https://api.smartthings.com/virtualdevices/{{deviceId}}/events with the JSON body:

{
  "deviceEvents": [
    {
      "component": "main",
      "capability": "presenceSensor",
      "attribute": "presence",
      "value": "present"
    }
  ]
}

Do make sure you are using a token for the location owner otherwise you’ll get a 403 error.

2 Likes

Belatedly revisiting this as I found myself in this thread …

The ones the CLI guides you into creating are cloud based, but that isn’t the whole story. I think it is ST’s story to be told but …

> smartthing virtualdevices
───────────────────────────────────────────────────────────────
 #  Label                 Device Id
───────────────────────────────────────────────────────────────
 1  Alexa Switch          XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
 2  Local Virtual Switch  XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
───────────────────────────────────────────────────────────────

Number 2 was built using the CLI using a prototype but is using the Virtual Switch Edge driver in the beta channel.
Number 1 was built using the CLI as a custom virtual device and is using a tweaked version of the Virtual Switch Edge driver in a private channel that has added a contact sensor.

In both cases the device driver was installed on the required hub for me.

So although it isn’t quite clear what the whole story is with the virtual devices, there is room for optimism about them.

That said, it isn’t clear how to make the equivalent of what I called the Alexa switch that would run in the cloud. Not using the CLI anyway.

1 Like

Thank you @orangebucket & @Jake_Mohl that worked.

Now I can use Tasker for presence sending with @lmullineux new hubless Virtual Presence Sensor that does not contain a switch.

1 Like

@orangebucket do you have a link to info about the events and virtual devices documentation?

I am not sure there is any. I just keep a close eye on the API reference and the CLI and Core SDK GitHub repos, and if something new comes along in the CLI I run it in debug mode to see what it is up to. Every now and again the bits fall into place.

Thank you for the info shared, @orangebucket!

The create device events endpoint is included here:

It says it’s used for devices created using a SmartApp Connector, so, I’ll check with the team if we can modify that description so, we have a better idea of where we can use it.

1 Like

Can you point me to where you found the correct json format in the repo?

There is a separate virtualdevices endpoint so it might be a bit confusing, even though bits like this are identical to the devices one.

Ah, that’s right. Sorry, I only saw the last part.
I’ll keep a note about this to see if this is considered for the information that will be shared about Virtual Devices.

https://github.com/SmartThingsCommunity/smartthings-core-sdk/tree/main/src/endpoint is the most useful place for info about endpoints. You have to follow the hierarchy of objects but what you end up with will match the JSON required by the API.

However if you can do something in the CLI and want to know how to do it in the API then the best way is to turn on the debug mode (in Windows it is set SMARTTHINGS_DEBUG=true) and see what it did. The CLI uses Axios and the various components of the HTTP requests are displayed.

2 Likes

OMIGOD!

Thanks for this tip…Would be nice to have a wiki page of developer tips…

I’m attempting to make sense of what you mean by this by using you example for the VR presence sensor but I’m failing ro see how you came to, using the the GitHub repo.

Let’s start with https://github.com/SmartThingsCommunity/smartthings-core-sdk/blob/main/src/endpoint/virtualdevices.ts as we know that we are interested in virtual devices. So we already know the endpoint we are interested in is likely to be https://api.smartthings.com/virtualdevices otherwise they’d have called the file something else.

So let’s look for something in the file about creating events. It is on lines 82-89. I can’t read TypeScript/JavaScript that brilliantly but line 89 suggests to me we are doing a POST to https://api.smartthings.com/virtualdevices/{{deviceId}}/events and the body is, in TypeScript/JavaScript terms, { deviceEvents }. We also know from the previous line that deviceEvents is an array of whatever DeviceEvent is.

So effectively it is { deviceEvents: [ DeviceEvent ] } and now we have to find DeviceEvent.

Line 3 shows that DeviceEvent is actually found in https://github.com/SmartThingsCommunity/smartthings-core-sdk/blob/main/src/endpoint/devices.ts. If we go to lines 511-522 we find:

export interface DeviceEvent {
	value: unknown
	component: string
	capability: string
	attribute: string
	unit?: string
	data?: { [name: string]: object }
}

export interface DeviceEventList {
	deviceEvents: DeviceEvent[]
}

So there we have the definition of deviceEvents as a list of DeviceEvent and above it is the definition of DeviceEvent. So let’s glue them together.

{
  deviceEvents: [
    {
      value: unknown
	  component: string
	  capability: string
	  attribute: string
	  unit?: string
	  data?: { [name: string]: object }
    }
  ]
}

That is now starting to resemble an event. We have the component, capability and attribute, a value, an optional unit and some optional extra data (where they used to stick buttonNumber and things like that). So let’s fill in some real data. In the same order I just gave (having moved value) we have main, presenceSensor, presence, present and we don’t need the other stuff. So we have:

{
  deviceEvents: [
    { 
      component: "main",
      capability: "presenceSensor",
      attribute: "presence",
      value: "present"
    }
  ]
}

Unsurprisingly JSON, the JavaScript Object Notation, is pretty similar to that. It just needs the quotes around the keys too.

{
  "deviceEvents": [
    {
      "component": "main",
      "capability": "presenceSensor",
      "attribute": "presence",
      "value": "present"
    }
  ]
}

As I say though, if you know the CLI command you can get places quicker.

> set SMARTTHINGS_DEBUG=true
> smartthings virtualdevices:events {{deviceId}} presenceSensor:presence present

That first fetched the capability so it can check you are asking something sensible and it will then pop up:

[2022-10-13T19:44:55.552] [DEBUG] rest-client - making axios request: {"url":"https://api.smartthings.com/virtualdevices/{{deviceId}}/events","method":"post","headers":{"Content-Type":"application/json;charset=utf-8","Accept":"application/json","User-Agent":"@smartthings/cli/1.0.0-beta.20 win32-x64 node-v16.16.0","Accept-Language":"en-GB","Authorization":"Bearer {{Personal Access Token}"},"data":{"deviceEvents":[{"component":"main","capability":"presenceSensor","attribute":"presence","value":"present"}]}}

That was a very good write up. Thank you for that hopefully I will be able to put that to some use in the future.