In general, Cancel is propagated from the top to the bottom. So if you want to use the cancel mechanism, then the command handler first has to issue it (or be triggered by its parent handler) and then this will reach the object. But this is not what you want anyway. You want the object to throw the error and then this error to propagate from bottom to the top. The error _event_ is propagated upwards automatically, but this is really only for showing the event. This has no control effect. For this you need to look at the ExecState of your hierarchy, like you correctly do, and investigate what happens to the states and how they switch to error (the unit state OpconUnitState.ERROR and events of type OpconEventClass.ERROR are two separate and only loosely connected concepts). If a unit switches to error, then this is _not_ automatically propagated upwards. In your normal station application this seems to happen but this is a feature that comes from your handlers' command chains using ExecuteUnit(RepeatOnError := FALSE, ..) or CheckUnitDone(RepeatOnError := FALSE, ...). The application guideline has some very detailed description about this mechanism. Everyone should be familiar with this. But the application guideline will not have a straight answer to your problem. Here are some things that you can do: Have the handler check the unit state of the TCU and somehow stop itself when it sees its TCU unit switch to error. This moves the logic out of your object, so you get no reusability with this solution. I also generally don't recommend to do it this way, because you'll have to put some control flow influencing logic in your command handler's OnUnitOperational or somewhere similar. Simple, but ugly. Change your object's commands so that it requires constant execution of the run command. This is how most automatic chains are realized in the command handlers and it works for objects, too. The user has to leave the Execute input on your TCU on TRUE for as long as it is working. In that case you won't really need a stop command and your start command should probably be called ControlTemperature instead or something. In order to stop you need a ParImm or something. Also, if you can change parameters during running, then those also need to use ParImm instead of a command. With some description of your TcuCmdEnum.CONTROL_TEMPERATURE item in the object you can convey this way of operation quite easily to your users. They will then use CheckUnitDone/ExecuteUnit with RepeatOnError := FALSE and get the effect that you want. But this is ugly for manual functions, possibly ATD and may not make the object seem very object-y. Give the unit a ParCfg member that links back to its parent unit (I think this is also available in _stdUnitData or some such variable?) and use that to trigger a cancel or whatever reaction you really need on the father handler. This way, the unit gets some control of the parent handler, which is generally a BAD idea, but depending on circumstances might be the least of all evil. If you go this route, please add a parameter to the object like "Trigger parent cancel on error yes/no", so the user knows that your device has this capability and can switch it off to regain full control of their command handler. Then they need to handle it themselves (like option 1). Maybe somebody else has some other suggestions? I would probably pick option 1 and delegate the problem to the parent command handler. When programming an object, it is not that object's task to manipulate the control flow of the entire station's application it is embedded in. That is the business of the handlers, which are programmed by the application engineers. You may want to put some hints and possibly examples in your object documentation to inform your object users that this is a common pattern they might need in their application.
... View more