Help converting complex DSL rule to Jython

I am slowly migrating my DSL rules over to Jython and been fairly successful so far with basic rules (if this happens, then switch that, etc).

On a more complex level, I have an alarm panel which interfaces through TCP. Using NodeRed I monitor for changes in the alarm panel (using Elk_Bridge item) and then update another item (Elk_Text). The Elk_Bridge item contains around 14-16 characters. The rule has 148 lines and is a series of nested IF and switch statements which interpret certain key characters within the Elk_Bridge item. While I can convert this to Jython based on what I have learnt so far (except for the switch statements) I think it can be done better, but I’m not actually sure of the recommended approach.

After some initial research I think my options may include either a hash map (don’t know much about this, yet) or possibly using a transformation map. Before I choose one and go further down the rabbit hole, I just wanted to know if either of these options are straight out wrong, or if there is a better option I haven’t yet considered. This will allow me to target my research a little better.

Any advice is appreciated

rule "Update Security"
    when
        Item Elk_Bridge received update
    then
        if (Elk_Bridge.state.toString.substring(0,2) == "82"){              //Status Report Data
            switch Elk_Bridge.state.toString.substring(8,10) {
                case "11" : {                                                   //Zone Detector Low Battery
                    switch Elk_Bridge.state.toString.substring(10,14) {
                        case "0000" : Elk_Text.postUpdate("Zone Detector Battery Normal")
                    }
                }
                case "12" : {                                                   //Miscellaneous Alarms
                    switch Elk_Bridge.state.toString.substring(10,14) {
                        case "0000" : Elk_Text.postUpdate("No Zones")
                        case "0100" : Elk_Text.postUpdate("Zone 1")
                    }
                }
                case "13" : {                                                   //Miscellaneous Alarms
                    switch Elk_Bridge.state.toString.substring(10,14) {
                        case "0001" : Elk_Text.postUpdate("Duress Alarm")
                        case "0002" : Elk_Text.postUpdate("Panic Alarm")
                        case "0004" : Elk_Text.postUpdate("Medical Alarm")
                        case "0020" : Elk_Text.postUpdate("Install End")
                        case "0040" : Elk_Text.postUpdate("Exit Tamper")
                        case "0080" : Elk_Text.postUpdate("Keypad Tamper")
                        case "0100" : Elk_Text.postUpdate("Pendant Panic")
                        case "0200" : Elk_Text.postUpdate("Panel Battery Low")
                        case "0400" : Elk_Text.postUpdate("Panel Battery Low")
                        case "0800" : Elk_Text.postUpdate("Mains Fail")
                        case "4000" : Elk_Text.postUpdate("Unknown Status 4000")
                        case "5000" : Elk_Text.postUpdate("Unknown Status 5000")
                    }
                }

Yep, your best bet is probably a dict (Python name for a Map) or using the Map transformation.

Do what ever you need to extract the characters you care about, concatenate them together and use that as the “key” into the dict/map.

For example,

key = Elk_Bridge.state.toString.substring(0,2)+Elk_Bridge.state.toString.substring(8,10)+Elk_Bridge.state.toString.substring(10,14)
text = mappings[key]

But keep in mind that this isn’t really going to save you many extra lines of code. Most of the lines where you have a postUpdate will be repeated as you populate a big dict inline in the code or a .map file.

Thanks so much @rlkoshak. It was easier than I thought.

I got it down to 90 lines. The dict takes up most of the room and the actual code is only a few lines. Also being in the dict makes the codes so much more maintainable compared with what I had before. I have to test it a bit more and then integrate it with the other functions, but I’m pretty happy with where I ended up. Thanks again for your suggestion and nudge in the right direction.

@rule ("Interpret Alarm Panel Codes", description="Interpret Alarm Panel Codes")
@when ("Item Elk_Bridge received update")
def interpret_codes(event):
	Elk_Bridge_String = str(items["Elk_Bridge"])
	key = str(Elk_Bridge_String[0:2] + Elk_Bridge_String[6:14])
	value = str(dictOfAlarmStatusReportCodes.get(key))
	interpret_codes.log.info(value)
	if (value[0:3] <> "PIR"):
		events.postUpdate("Elk_Text",value)

Example of the dict:

# Dictionary of Alarm Codes
dictOfAlarmStatusReportCodes = {
	"8260110000" : "Zone Detector Battery Normal",
	"8260120000" : "No Zones",
	"8260120100" : "Zone 1",
	etc