No announcement yet.

Help with --BuildUI --ProcessPostUI --FormatUI

This is a sticky topic.
  • Filter
  • Time
  • Show
Clear All
new posts

  • Help with --BuildUI --ProcessPostUI --FormatUI

    I wrote this in response to a plug-in author's request for clarification - it should go in the SDK and it will go in there, but I wanted to post it here for immediate help if this was a sticking point for others...

    The question was in regards to the flow and interaction of Trigger/ActionBuildUI and Trigger/ActionProcessPostUI - I hope this helps.

    Both procedures get passed strTrigActInfo which contains key information that you need. It has an event reference number, an action number, and even if the user adds 5 of the same action to an event, there is an ID which is unique across all of the actions. Any/all of this information is used by you to manage the action. In ActionBuildUI, you create the UI for the action if it is new. If it is not new, then you can use the information in strTrigActInfo to get an object or data from your plug-in that tells you what options the user chose for the action. (More on that in a minute.) When ActionPostUI is called, the same information is there, but now you are processing the things that the user entered and are possibly making changes to your data or your object. Here is an example:
    ActionBuildUI - evRef=1234, TANumber (Action)=2, SubTANumber (SubAction)=0, UID=587469853254.

    Using the information above, you look in your data store and you do not have this action's data, so it is new, and you present the user with a UI - let's say it is an action to have HomeSeer speak something, and you put a text box on the UI called "strSpeakText" where the user enters text to be spoken.
    ActionProcessPostUI - evRef=1234, TANumber (Action)=2, SubTANumber (SubAction)=0, UID=587469853254.

    Again using the information above, you see that the action does not exist, but this is the post which means the user probably entered some part of the configuration information for this action. You know by the action number and sub-action number (if you need that) that it is an action to speak something. You go through the data collection and find strSpeakText which is the value "Hello World". So, you create some object in your plug-in that stores action data, add "Hello World" to it, and then store it using a key you generate from the evRef, TANumber, and UID (we'll assume SubTANumber is not needed). You could use JUST the UID if you wanted since it is unique enough.

    Now the user is back at the UI, but if this simple action has no other configuration parameters, then ActionConfigured when called for this action will return True, and so the UI will show the configured action (ActionFormatUI) rather than the UI to make changes (ActionBuildUI).

    THAT is how those two procedures work together - your plug-in is responsible for holding the data somehow, but there is help as I will describe next...

    So your plug-in needs a way to store the triggers and actions that the user has created, and all the data that goes with them. For example, if the user creates an action that is to operate some device connected to your plug-in, then you need to give them a list of the devices, and what YOU need to store is the device that they chose.

    You can use an INI file, a database, or whatever you want to store this data, OR you can have HomeSeer store the data in the event. The way you do this is to serialize or deserialize whatever object it is that you are using to hold your data, and then pass the bytes back and forth between HomeSeer and your plug-in. Serializing takes an object - as simple as a single data type or as complex as an object with properties and procedures - and converts it into a data stream of bytes which has all of the information describing the object, as well as the data that goes into it.

    To do this, this is how it works. The other parameter of strTrigActInfo that I have not mentioned yet is DataIN, which is a byte array. If you told HomeSeer to store your object, then this array would have bytes in it. If the user is creating the action for the first time, then it will be null and empty. Using this byte array, you can call DeserializeObject, which we included in the sample plug-ins, and that will convert the bytes back into the complex object you created to store the data. Now when building the UI, you can see that the user already configured the action, and so ActionFormatUI displays that the user chose to have the action speak "Hello World".

    In ActionProcessPostUI, you are again given DataIN, so you reconstruct your data storage object, but the user made a change and had the action speak "Hello Cruel World" instead. So you update your object, and now in ActionProcessPostUI note that the RETURN object (strMultiReturn) has a parameter called DataOUT, which is a byte array. After you make changes to the storage object to reflect the new text to be spoken, you call SerializeObject, and the object is then converted into the byte array that you place into DataOUT, and now HomeSeer stores that data with the action to be saved in the HomeSeer database so you do not have to worry about it.

    That is how you can have HomeSeer store your data object for you.

    One LAST piece of information or option I will give you is that you may find it slow to have to convert the objects back and forth, and when calls such as Handle are made for actions, it takes time to convert the object back which slows things down. Thus, there are calls you can make to get all of the actions or all of the triggers for your plug-in, so you can store them locally and access them faster. The thing is, you need to keep them up to date, which means making sure that when a change comes through from the user, you remember to update your local copy, or just create a thread that updates all of the copies every 10-15 minutes or so. You should also use HSEvent to monitor for event changes, such as when a user deletes an event, so that you know to either remove the triggers and actions for that event from your local copy or to call your procedure which updates your local copy of your triggers and actions. Look at the callback procedures: callback.GetActions/GetTriggers/TriggerMatches for that.

    Rick Tinker (a.k.a. "Tink")

  • #2
    Thanks, this is the best explanation I have seen on this subject so far, and made me understand how to save the information from the UI into the plugin.

    Is it possible to add this into the SDK documentation, as that is where most developers are looking for information.