Premise invokeproperty bug?

Motorola Premise

etc6849

Senior Member
Very strange invokeproperty method. I don't understand it, so please feel free to help me :)

I was trying to toggle a device's power, using the code below:
Code:
'find the desired receiver
Set objRcvr = getReceiverInHome(0)
set objRcvr = objRcvr.boundobject

Set objProp = sys.GetObject("sys://Schema/Device/Power/PowerState")
Set objAction = sys.GetObject("sys://Schema/System/Boolean/Toggle")
objRcvr.InvokeProperty 9, objProp, objAction

This code changes both the home and device powerstate property values, but no command is sent. With this device, I do not have a toggle command set, but rather on and off commands. If you modify the above code to turn the device on instead of toggle (sys://Schema/System/Boolean/Toggle changes to sys://Schema/System/Boolean/On) it works just fine!

What is really confusing is the code below works and on/off commands are sent appropriately:
Code:
'find the desired receiver
Set objRcvr = getReceiverInHome(0)
'set objRcvr = objRcvr.boundobject

Set objProp = sys.GetObject("sys://Schema/Device/Power/PowerState")
Set objAction = sys.GetObject("sys://Schema/System/Boolean/Toggle")
objRcvr.InvokeProperty 9, objProp, objAction

In case you are wondering, you can also replace objRcvr with the direct path (devices.CustomDevices.TXNR905) and similar behavoir is observed. All getReceiverInHome() does is grab the nth receiver found under home and return the receiver object.

The help file says this:
InvokeProperty Method Premise Scripting Reference
InvokeProperty
object.InvokeProperty(ControlCode, Property, Action)

Arguments object (required) Any PremiseObject. ControlCode (required) Long value specifying the desired type of action on the property. Send the Property (required) Schema object of Property Object to be invoked. For example, Schema.Device.Power.PowerState Action(required) Schema object of action to be invoked. For example, Schema.System.Boolean.Toggle. Example 'toggle the power on the light referenced by this
Code:
'the 9 represents the SVCC_NOTIFY and SVCC_FORCE codes being sent to the method
set objProp = sys.GetObject("sys://Schema/Device/Power/PowerState")

set objAction = sys.GetObject("sys://Schema/System/Boolean/Toggle")

this.InvokeProperty 9, objProp, objAction
Remarks The InvokeProperty Method completes an action upon a property with a specified type of action based on the Control Code passed to the method. To send multiple flags, add the values of the flags together and send that number.
1 - SVCC_NOTIFY (notify updates within local machine) 2 - SVCC_UNDO (create undo unit(s)) 4 - SVCC_LOCAL (don't replicate with server; don't add to replication log) 8 - SVCC_FORCE (force update, even if property is the same) 16 - SVCC_EXIST (when creating, return an existing object if already there, when setting, indicates that property change is part of a command invocation) 64 - SVCC_FIXED (upon creation, sets object has fixed, so that it can't be deleted by a user)
 
I may be wrong but I've understood InvokeProperty to be a powerful method that, in practice, is rarely needed. Aside from its ability to use Flags, you can accomplish what it does in, to my mind, a simpler way.

InvokeProperty is kind of a "all-purpose method" that can act on any one of an object's many properties. In your example, it is being used to toggle the state of the PowerState property. Here's a simpler way to do that:
Code:
objRcvr.PowerState = not objRcvr.PowerState
Basically, we're setting objRcvr's Powerstate property to the opposite ("not") of its current state.

PS
I think we've discussed this in another thread but I don't think a "find the Nth receiver" function fits well into Premise's hierarchical data-store. I believe you indicated it works for you .. and that's great; but there's no guarantee that the second receiver will always remain the second one in Premise Home. The sixth Light in the data-store may become the seventh after you add a new Light somewhere in Home. Calling the object explicitly is more robust (i.e. Home.LivingRoom.MediaZone.Receiver or Home.FirstFloor.Kitchen.Nook.RecessedLights). You can use VBScript's "With ... End With" to keep the code tidy when using long path names:
Code:
with Home.SecondFloor.MasterBedroom.MasterBathroom.Sconces
	.PowerState = not .PowerState ' Toggle them
end with
 
I don't know how else to directly do what I'm trying to do without using the invokeproperty. I'm trying to invoke a receiver property I made called HDMIout and need to toggle it. Yes, I can use an if else statement to check the properties state first, but it'd be nice if I understood why the invokeproperty method wasn't working for me when I try to use the toggle action on device objects, but does this same action on home objects. What is interesting is passing other actions to device objects works just fine.

PS: Don't worry. The receiver subroutine won't simply search home and return the first receiver for much longer :rolleyes: I'm going to change the subroutine's code to return a home receiver object that I explicitly define within the subroutine given a passed integer. That way, if I change my room name or media name, I only need to change code in a single place. I plan to do this for most home objects (except lights) by writing a generic subroutine where I pass the device number and device type to get the corresponding home object. This would eliminate the need to ever go back and look at scripts after a major restructuring of the home objects, but still would use the explicit notation; just in a single place.

I may be wrong but I've understood InvokeProperty to be a powerful method that, in practice, is rarely needed. Aside from its ability to use Flags, you can accomplish what it does in, to my mind, a simpler way.

InvokeProperty is kind of a "all-purpose method" that can act on any one of an object's many properties. In your example, it is being used to toggle the state of the PowerState property. Here's a simpler way to do that:
Code:
objRcvr.PowerState = not objRcvr.PowerState
Basically, we're setting objRcvr's Powerstate property to the opposite ("not") of its current state.

PS
I think we've discussed this in another thread but I don't think a "find the Nth receiver" function fits well into Premise's hierarchical data-store. I believe you indicated it works for you .. and that's great; but there's no guarantee that the second receiver will always remain the second one in Premise Home. The sixth Light in the data-store may become the seventh after you add a new Light somewhere in Home. Calling the object explicitly is more robust (i.e. Home.LivingRoom.MediaZone.Receiver or Home.FirstFloor.Kitchen.Nook.RecessedLights). You can use VBScript's "With ... End With" to keep the code tidy when using long path names:
Code:
with Home.SecondFloor.MasterBedroom.MasterBathroom.Sconces
	.PowerState = not .PowerState ' Toggle them
end with
 
I don't know how else to directly do what I'm trying to do without using the invokeproperty. I'm trying to invoke a receiver property I made called HDMIout and need to toggle it.

Code:
set oRcvr = home.someroom.mediazone.receiver
oRcvr.HDMIout = not oRcvr.HDMIout ' toggle HDMIout property

I don't know why InvokeProperty fails to toggle Devices but works for Home objects. But that shouldn't prove to be a huge obstacle because all programming logic should operate with Home objects exclusively and not attempt to manipulate Devices directly. The advantage of this arrangement is device-independence; bind the Home object to a new Device and the programming logic continues to work correctly. It won't work if the logic contains explicit references to Devices.

I'm simply stating Premise's design philosophy. Feel free to do what works for you; Premise is flexible.
 
I normally try to use the home object, but since I added a new property to the receiver module call HDMIout, I am forced to link to the device for now. I might create a home object with the HDMIout property. The new home object would have an unbound property if I used it with a different receiver.

Do you guys normally create your own home objects too if you add properties? I did this for a multi zone driver I am working on and all it amounted too was copying from the current home class and pasting the class under modules.

I don't know how else to directly do what I'm trying to do without using the invokeproperty. I'm trying to invoke a receiver property I made called HDMIout and need to toggle it.

Code:
set oRcvr = home.someroom.mediazone.receiver
oRcvr.HDMIout = not oRcvr.HDMIout ' toggle HDMIout property

I don't know why InvokeProperty fails to toggle Devices but works for Home objects. But that shouldn't prove to be a huge obstacle because all programming logic should operate with Home objects exclusively and not attempt to manipulate Devices directly. The advantage of this arrangement is device-independence; bind the Home object to a new Device and the programming logic continues to work correctly. It won't work if the logic contains explicit references to Devices.

I'm simply stating Premise's design philosophy. Feel free to do what works for you; Premise is flexible.
 
... Do you guys normally create your own home objects too if you add properties? ...
  1. New Class
    If Premise lacks a class I need, then I'll create it.
    For example, I needed a "LockSensor" class so I created one that inherits from the existing DigitalInput class.
  2. New Property
    If Premise has a class that lacks a property I need, then I'll extend it.
    For example, let's assume the existing Receiver class does everything you need but simply lacks an HDMIOut property. Create a new class that has an Extension relationship with the Receiver_Base class. All Receiver objects will automatically acquire the HDMIOut property.
I've attached a Module that extends Receiver_Base with three new properties. Import it and all of your existing Receiver obejcts will acquire three new properties.
 

Attachments

It sure does extend the property! How neat. I can see how this could be a very useful feature. Very powerful compared to just adding a property to an existing module class. I also like how you grouped the new properties into their own class.

... Do you guys normally create your own home objects too if you add properties? ...
  1. New Class
    If Premise lacks a class I need, then I'll create it.
    For example, I needed a "LockSensor" class so I created one that inherits from the existing DigitalInput class.
  2. New Property
    If Premise has a class that lacks a property I need, then I'll extend it.
    For example, let's assume the existing Receiver class does everything you need but simply lacks an HDMIOut property. Create a new class that has an Extension relationship with the Receiver_Base class. All Receiver objects will automatically acquire the HDMIOut property.
I've attached a Module that extends Receiver_Base with three new properties. Import it and all of your existing Receiver obejcts will acquire three new properties.
 
Back
Top