This is absolutely possible, and it's no different from a "standard"/capability command--they're all just implemented as Groovy methods in the driver, and once you get a reference to the device(s), you can call that method like any command from a custom app. So instead of
myDevice.on(), as it sounds like you may be used to, you call
myDevice.customCommand(param1, param2) or whatever.
This assumes you know the basics of how to get a device reference in an app, which is done via an
input where you have the user select a device. This is often done by capability (though there is a way to select for a specific driver if you really want), but the specific capability you use does not matter — once you get a reference to the device, you can call any command (and access any attribute) on it. Something like:
input name: "myDevice", type: "capability.switch", title: "Choose device"
If you add
multuple: true, you'll be able to select multiple devices, and you'll get a list instead of a single object (technically a
DeviceWrapperList instead of a
DeviceWrapper), but you can call methods for commands directly on either type of object, so there shouldn't be any difference just for this.
Subscriptions are not relevant, as you do not need one to send a command. They are necessary if you want your app to wake (generally because you want it to do something) in response to an event from the device. Custom attributes work the same as "standard"/capability attributes here, too, however, should you need that for other purposes.