Fire alarm trigger and notification

That is incorrect. The rule sends a message when either the temperature goes over 45 OR a smoke detector goes off.

If you set up persistence you can sort the alarms and temps by lastUpdate to get the message to list each in the order that they triggered.

Make sure all the triggering Items are persisted.

Then change the rule to:

import java.util.List

rule "Alarm!"
when
    Item gTemperatures changed or                   // Trigger when the max temp of all sensors changes
    Item gSmokeDetectors changed to ON        // OR trigger when one or more of the smoke detectors goes off
then

    // If there is no alarm state (i.e. all smoke detectors are OFF and all temperatures are <= 45) exit the rule
    if(gSmokeDetectors.state != ON && gTemperatures.state as Number <= 45) return;

    val List<GenericItem> alarms = newArrayList

    // Get all the temperature Items that are above 45
    alarms.addAll(gTemperatures.members.filter[t|t.state as Number > 45])

    // Get all the smoke alarms that are ON
    alarms.addAll(gSmokeDetectors.members.filter[s|s.state == ON])

    // Sort them to be in the order they were most recently changed, oldest alarm listed first
    val sorted = alarms.sortBy[lastUpdate]

    val message = new StringBuilder()

    // Build up the message listing the oldest alarms first and most recent last.
    message.append("The following alarms are active: ")

    sorted.forEach[i|
        if(i instanceof NumberItem) message.append(transform("MAP", "alarm.map", i.name) + " = " + i.state.toString + ", ")
        else message.append(transform("MAP", "alarm.map", i.name) + ", ")
    ]

    message.delete(message.length - 2, message.length) // delete the extraneous ", "

    // send message
end