SmartThingsCommunity / smartapp-sdk-nodejs

Javascript/NodeJS SDK to create SmartThings SmartApps
https://smartthings.developer.samsung.com/
Apache License 2.0
142 stars 80 forks source link

question: design limitation precludes a common event handler? #226

Open toddaustin07 opened 2 years ago

toddaustin07 commented 2 years ago

When defining device subscription handlers, you cannot name a common handler across subscriptions. The SDK design seems to impose a unique handler name for each subscription. If I want to support nearly all SmartThings capabilities, I would have a potentially LARGE number of subscriptions to handle, but the current design forces me to declare a unique handler for each, resulting in an unnecessary proliferation of code.

What I want to do is this:

context.api.subscriptions.subscribeToDevices(context.config.buttonList, 'button', 'button', 'commonhandler'))
context.api.subscriptions.subscribeToDevices(context.config.contactList, contactSensor', contact', 'commonhandler'))
.
.
.
context.api.subscriptions.subscribeToDevices(context.config.motionList, 'motionSensor', motion', 'commonhandler'))

subscribedEventHandler('commonHandler', (context, deviceEvent) => {
   <do common stuff>
}

However, I get a subscriptionName conflict error if I try to do that. What I seem to be forced to do is define unique handlers for each like this:

context.api.subscriptions.subscribeToDevices(context.config.buttonList, 'button', 'button', 'buttonhandler'))
context.api.subscriptions.subscribeToDevices(context.config.contactList, contactSensor', contact', 'contacthandler'))
.
.
.
context.api.subscriptions.subscribeToDevices(context.config.motionList, 'motionSensor', motion', 'motionhandler'))

subscribedEventHandler('buttonHandler', (context, deviceEvent) => {
   <do same stuff, or call a common do-stuff routine here>
}

subscribedEventHandler('contactHandler', (context, deviceEvent) => {
   <do same stuff, or call a common do-stuff routine here>
}
.
.
.
subscribedEventHandler('motionHandler', (context, deviceEvent) => {
   <do same stuff, or call a common do-stuff routine here>
}

Is there a better way to accomplish this or perhaps this is a needed design change in the SDK?

bflorian commented 2 years ago

Unique subscription names are a limitation of the underlying API, not just the SDK, but I can't think of any reason offhand why they need to be unique. We'll investigate.

bflorian commented 2 years ago

We're pursuing an API change that will no longer require subscription names to be unique. We'll leave this issue open and update it when we have a release date.

A work-around you could do in the meantime is to declare the handler separately from the handler registration commands. It's still more code than should be necessary, but a little more maintainable than having a separate inline function in each subscribedEventHandler call.

const deviceHandler = (context, deviceEvent) => {
  <do some stuff>
}

subscribedEventHandler('buttonHandler', deviceHandler)
subscribedEventHandler('contactHandler', deviceHandler)
.
.
.
subscribedEventHandler('motionHandler', , deviceHandler)