Script to Email Item State Report

Problem Statement: I am trying to create a script that can be called from rules to give an status report or state of some or all items depending on the reason I am calling it (I can change the scripts parameters once I get the base copy working). In the beginning I would just like to get a daily report of all item states. Using various blogs and yoyotech’s video I have come this far:

rule "Test Script"
	when   
		Time cron "00 00 23 ? * * *"
	then
		callScript("test")
		pushover("Test Alert")
	end

The rule works. Next I have my script which is working until I get to the gINLights.members section.

var frontDoor = "c:\\Program Files (x86)\\GnuWin32\\bin\\wget.exe --output-document c:\\openHAB2\\temp\\frontdoor.jpg http://user:pass@192.168.x.x/Streaming/channels/1/picture"
var southYard = "c:\\Program Files (x86)\\GnuWin32\\bin\\wget.exe --output-document c:\\openHAB2\\temp\\southyard.jpg http://user:pass@192.168.x.x/Streaming/channels/1/picture"
var driveWay = "c:\\Program Files (x86)\\GnuWin32\\bin\\wget.exe --output-document c:\\openHAB2\\temp\\driveway.jpg http://user:pass@192.168.x.x/Streaming/channels/1/picture"
var backYard1 = "c:\\Program Files (x86)\\GnuWin32\\bin\\wget.exe --output-document c:\\openHAB2\\temp\\backyard1.jpg http://user:pass@192.168.x.x/Streaming/channels/1/picture"
var northYard = "c:\\Program Files (x86)\\GnuWin32\\bin\\wget.exe --output-document c:\\openHAB2\\temp\\northyard.jpg http://user:pass@192.168.x.x/Streaming/channels/1/picture"
var backYard2 = "c:\\Program Files (x86)\\GnuWin32\\bin\\wget.exe --output-document c:\\openHAB2\\temp\\backyard2.jpg http://user:pass@192.168.x.x/Streaming/channels/1/picture"
executeCommandLine(frontDoor, 4000)
executeCommandLine(southYard, 4000)
executeCommandLine(driveWay, 4000)
executeCommandLine(backYard1, 4000)
executeCommandLine(northYard, 4000)
executeCommandLine(backYard2, 4000)
var insideLights = "*** Inside Lights***"
var outsideLights = "*** Outside Lights***"
var theDate = new DateTimeType()
theDate = theDate.format("%1$ta %1$tb %1$te, $1$tC%1$ty - %1$tR")
val attachmentUrlList = newArrayList(
   "file:c:\\openHAB2\\temp\\frontdoor.jpg",
   "file:c:\\openHAB2\\temp\\southyard.jpg",
   "file:c:\\openHAB2\\temp\\northyard.jpg",
   "file:c:\\openHAB2\\temp\\driveway.jpg",
   "file:c:\\openHAB2\\temp\\northyard.jpg",
   "file:c:\\openHAB2\\temp\\southyard.jpg")

gIN_Lights.members.forEach[item | insideLights = insideLights + "\n" + item.label + " : " + item.state]
gEX_Lights.members.forEach[item | outsideLights = outsideLights + "\n" + item.lbel + " : " + item.state]
        
val mailActions = getActions("mail", "mail:smtp:sendgrid")
mailActions.sendHtmlMail("my@email.com", "This is a test Email", "This is a test Email.  End", attachmentUrlList)

I then need additional code to get this into the Email body, but I have not made it that far. I’m using Visual Studio Code and it’s not throwing up any errors.

You want to add text to your email?

mailActions.sendHtmlMail("my@email.com", "This is a test Email", "This is a test Email. " + insideLights + outsideLights + " End", attachmentUrlList)

I’m not sure if it will help, but State is not a string, so you could try changing to item.state.toString.

This helped with the Email subject and getting the insideLights and outsideLights headings into the body, but the code to enumerate and list item states is still not working. When I un-comment the two lines of code that are supposed to handle this, the script fails.

I’m pretty certain you cannot change a var from inside a forEach lambda. You should be seeing errors mentioning something like “cannot use non-final variable”, at least that used to be the case.

There are two approaches you can use here to get past this problem. Use a StringBuilder or use a reduce.

import java.util.StringBuilder

...

    val insideLights = new StringBuilder()
    insideLights.add("*** Inside Lights ***")
    ...
    gIN_Lights.members.forEach[ item | insideLights.add("\n" + item.label + " : " + item.state) ]

or

    val insideLights = "*** Inside Lights***" + gIN_Lights.members.reduce[ msg, item | msg = msg + "\n" + item.label + " : " + item.state ]

There are additional examples of this in Design Pattern: Working with Groups in Rules.

Method 1:

var outsideLights = "*** Outside Lights ***"
var theDate = new DateTimeType()
theDate = theDate.format("%1$ta %1$te %1$tb %1$tY - %1$tR")
val attachmentUrlList = newArrayList(
   "file:c:\\openHAB2\\temp\\frontdoor.jpg",
   "file:c:\\openHAB2\\temp\\southyard.jpg",
   "file:c:\\openHAB2\\temp\\northyard.jpg",
   "file:c:\\openHAB2\\temp\\driveway.jpg",
   "file:c:\\openHAB2\\temp\\northyard.jpg",
   "file:c:\\openHAB2\\temp\\southyard.jpg")    

    val insideLights = new StringBuilder()
    insideLights.add("*** Inside Lights ***")
    gIN_Lights.members.forEach[ item | insideLights.add("\n" + item.label + " : " + item.state) ]
    //gIN_Lights.members.forEach[item | insideLights = insideLights + "\n" + item.label + " : " + item.state.toString]
    //gEX_Lights.members.forEach[item | outsideLights = outsideLights + "\n" + item.lbel + " : " + item.state.toString]
        
val mailActions = getActions("mail", "mail:smtp:sendgrid")
mailActions.sendHtmlMail(my@email.com", "This is a test Email " + theDate, "Status Report for Home:" + "

" + insideLights + "

" + outsideLights + "

" + " End", attachmentUrlList)

M1 Log output (with import):

2020-04-22 18:53:00.156 [ERROR] [ntime.internal.engine.ExecuteRuleJob] - Error during the execution of rule 'Test Script': The name 'import' cannot be resolved to an item or type; line 1, column 1, length 6

M1 Log output (without import):

2020-04-22 18:51:04.440 [ERROR] [ntime.internal.engine.ExecuteRuleJob] - Error during the execution of rule 'Test Script': 'add' is not a member of 'java.lang.StringBuilder'; line 26, column 5, length 41

Method 2:

val insideLights = "*** Inside Lights***" + gIN_Lights.members.reduce[ msg, item | msg = msg + "\n" + item.label + " : " + item.state ]
var outsideLights = "*** Outside Lights ***"
var theDate = new DateTimeType()
theDate = theDate.format("%1$ta %1$te %1$tb %1$tY - %1$tR")
val attachmentUrlList = newArrayList(
   "file:c:\\openHAB2\\temp\\frontdoor.jpg",
   "file:c:\\openHAB2\\temp\\southyard.jpg",
   "file:c:\\openHAB2\\temp\\northyard.jpg",
   "file:c:\\openHAB2\\temp\\driveway.jpg",
   "file:c:\\openHAB2\\temp\\northyard.jpg",
   "file:c:\\openHAB2\\temp\\southyard.jpg")

    

    //gIN_Lights.members.forEach[ item | insideLights.add("\n" + item.label + " : " + item.state) ]
    //gIN_Lights.members.forEach[item | insideLights = insideLights + "\n" + item.label + " : " + item.state.toString]
    //gEX_Lights.members.forEach[item | outsideLights = outsideLights + "\n" + item.lbel + " : " + item.state.toString]
        
val mailActions = getActions("mail", "mail:smtp:sendgrid")
mailActions.sendHtmlMail("my@email.com", "This is a test Email " + theDate, "Status Report for Home:" + "

" + insideLights + "

" + outsideLights + "

" + " End", attachmentUrlList)

M2 Log output:

2020-04-22 18:46:04.403 [ERROR] [ntime.internal.engine.ExecuteRuleJob] - Error during the execution of rule 'Test Script': Couldn't invoke 'assignValueTo' for feature param msg

I was going from memory so I got a couple of things wrong.

  • StringBuilder is in java.lang, not java.util so you don’t have to import it
  • the method to call is append, not add

The second one is also a typo on my part. I don’t use Rules DSL any longer so some of the gotchas are no longer at the tip of my brain. You don’t assign the results to msg inside the reduce.

....reduce[ msg, item | msg + "\n" + item.label + " : " + item.state ]

So I got it working with Method 2 making the corrections you indicated. Excitement. The only odd thing is that the first item it lists, it lists a bunch of information from the Items file and not necessarily the friendly name, then the rest of the items show up with their friendly names. Any idea on this behavior?

Code:

val insideLights = "*** Inside Lights***" + "\n" + gIN_Lights.members.reduce[msg, item | msg + "\n" + item.label + " : " + item.state ]

Results in Email:

*** Inside Lights***

GF_LR_EastLamp_Pwr (Type=DimmerItem, State=100, Label=LR East Lamp, Category=switch, Tags=[Lighting], Groups=[gGF_Living, gGF_Scene, gGF_Lights, gIN_Lights])
LR South Lamp : 100
LR Pole Lamp : 96
FR Table Lamp : 51
FR Can Lights : 0
DR Chandalier : 0
DR Can Lights : 0

Confirmed the same behavior on other groups; outsideLights, motionSensors. The first item listed always has the extraneous detail.

This error is also indicated in Visual Studio Code, but the script executes with the above results anyway.

Hmmmm, that’s pretty odd but I think I may know what is going on.

msg has to be initialized with something to start with. It usually initializes the Item with the first member of the List it’s reducing. The List, in this case, is a list of Items so it initializes msg with the first Item. Next time through the loop it appends the label and state to that first Item’s toString so you get that first line.

It might be better using StringBuilder but there is something you could try. I have no idea if either of these approaches will work:

Approach 1:

....reduce[ msg="", item | msg + "\n" + ...

Approach 2a:

....members.map[ item | item.label + " : " + item.state].reduce[ msg, line | msg + "\n" + line ]

Approach 2b:

....members.map[ label + " : " + state ].reduce[ msg, line | msg + "\n" + line ]

Approach 1 tries to give the msg, which stores the result of the reduce, with “” which may short circuit the initialization of it with the first member of the List.

Approaches 2 uses the map operation to extract the label and state String so the reduce only get’s a List of Strings to append. I’ve never used a map with two calls to methods on the Item so I’m not sure which if either of the two approaches will work.

Approach 2a. Final code:

var frontDoor = "c:\\Program Files (x86)\\GnuWin32\\bin\\wget.exe --output-document c:\\openHAB2\\temp\\frontdoor.jpg http://user:pass@192.168.x.x/Streaming/channels/1/picture"
var southYard = "c:\\Program Files (x86)\\GnuWin32\\bin\\wget.exe --output-document c:\\openHAB2\\temp\\southyard.jpg http://user:pass@192.168.x.x/Streaming/channels/1/picture"
var driveWay = "c:\\Program Files (x86)\\GnuWin32\\bin\\wget.exe --output-document c:\\openHAB2\\temp\\driveway.jpg http://user:pass@192.168.x.x/Streaming/channels/1/picture"
var backYard1 = "c:\\Program Files (x86)\\GnuWin32\\bin\\wget.exe --output-document c:\\openHAB2\\temp\\backyard1.jpg http://user:pass@192.168.x.x/Streaming/channels/1/picture"
var northYard = "c:\\Program Files (x86)\\GnuWin32\\bin\\wget.exe --output-document c:\\openHAB2\\temp\\northyard.jpg http://user:pass@192.168.x.x/Streaming/channels/1/picture"
var backYard2 = "c:\\Program Files (x86)\\GnuWin32\\bin\\wget.exe --output-document c:\\openHAB2\\temp\\backyard2.jpg http://user:pass@192.168.x.x/Streaming/channels/1/picture"
executeCommandLine(frontDoor, 4000)
executeCommandLine(southYard, 4000)
executeCommandLine(driveWay, 4000)
executeCommandLine(backYard1, 4000)
executeCommandLine(northYard, 4000)
executeCommandLine(backYard2, 4000)//
var theDate = new DateTimeType()
    theDate = theDate.format("%1$ta %1$te %1$tb %1$tY - %1$tR")
val attachmentUrlList = newArrayList(
   "file:c:\\openHAB2\\temp\\frontdoor.jpg",
   "file:c:\\openHAB2\\temp\\southyard.jpg",
   "file:c:\\openHAB2\\temp\\northyard.jpg",
   "file:c:\\openHAB2\\temp\\driveway.jpg",
   "file:c:\\openHAB2\\temp\\northyard.jpg",
   "file:c:\\openHAB2\\temp\\southyard.jpg")    
val insideLights = "*** Inside Lights***" + "\n" + gIN_Lights.members.map[ item | item.label + " : " + item.state].reduce[ msg, line | msg + "\n" + line ]
val outsideLights = "*** Outside Lights***" + "\n" + gEX_Lights.members.map[ item | item.label + " : " + item.state].reduce[ msg, line | msg + "\n" + line ]
val motionSensors = "*** Motion Sensors***" + "\n" + gEX_MotionSens.members.map[ item | item.label + " : " + item.state].reduce[ msg, line | msg + "\n" + line ]

  
val mailActions = getActions("mail", "mail:smtp:sendgrid")
mailActions.sendHtmlMail("my@email.com", "This is a test Email " + theDate, "Status Report for Home:" + "\n" +"\n" + insideLights + "\n" +"\n" + outsideLights + "\n" +"\n" + motionSensors + "\n" +"\n" + " End", attachmentUrlList)
1 Like

Here’s how I set mine up - I only want to know what is ON or PLAYING vs. the status of everything when we are traveling.

rule "eMail Report What is ON While Away"
    when 
        Time cron "0 11 8 ? * * *"	or				// 8:11 AM Daily
        Time cron "0 11 14 ? * * *"	or				// 2:11 PM Daily
		Time cron "0 11 22 ? * * *"	or				// 10:11 PM Daily
		Item Away_Report changed to ON
    then 
	
		if (systemStarted.state != ON && gInternet.state == ON && (Home_Away.state == OFF || Away_Report.state == ON)) {

			var SonosThingGym  			= getThingStatusInfo("sonos:CONNECTAMP:identifier").getStatus() 
		   	var SonosThingGround  		= getThingStatusInfo("sonos:CONNECTAMP:identifier").getStatus()	
	    	var SonosThingJay		 	= getThingStatusInfo("sonos:CONNECTAMP:identifier").getStatus() 
	    	var SonosThingOnWall	 	= getThingStatusInfo("sonos:CONNECTAMP:identifier").getStatus()	
	    	var SonosThingBasement1R	= getThingStatusInfo("sonos:PLAY1:identifier").getStatus()	 
	    	var SonosThingBasement2L	= getThingStatusInfo("sonos:PLAY1:identifier").getStatus() 
	    	var SonosThingLR1			= getThingStatusInfo("sonos:PLAY1:identifier").getStatus()	 
	    	var SonosThingLR2		 	= getThingStatusInfo("sonos:PLAY1:identifier").getStatus()	  
	    	var SonosThingLoft1		 	= getThingStatusInfo("sonos:PLAY1:identifier").getStatus()	  
	    	var SonosThingLoft2		 	= getThingStatusInfo("sonos:PLAY1:identifier").getStatus()	 
	    	var SonosThingRyan		 	= getThingStatusInfo("sonos:PLAY1:identifier").getStatus()	  
	    	var SonosThingTricia		= getThingStatusInfo("sonos:PLAY1:identifier").getStatus()	 
	    	var SonosThingMB			= getThingStatusInfo("sonos:PLAY1:identifier").getStatus()	
	    	var SonosThingMB2			= getThingStatusInfo("sonos:PLAY1:identifier").getStatus()	 
	    	var SonosThingKitchen		= getThingStatusInfo("sonos:PLAY1:identifier").getStatus()	
	
			var awaymessage = new StringBuilder()
	
			if (systemStarted.state != ON)														{ awaymessage.append("\n ------------------------------------------------------------------------ ")}
			if (systemStarted.state != ON)														{ awaymessage.append("\n ** WeMo Devices = ON Now **")}
			if (systemStarted.state != ON)														{ awaymessage.append("\n ------------------------------------------------------------------------ ")}
			if (systemStarted.state != ON && Switch_Backdoor_Light.state == ON)					{ awaymessage.append("\n - Switch_Backdoor_Light") }
			if (systemStarted.state != ON && Switch_Frontdoor_Light.state == ON)				{ awaymessage.append("\n - Switch_Frontdoor_Light") }
			if (systemStarted.state != ON && Switch_Basement_Light.state == ON) 				{ awaymessage.append("\n - Switch_Basement_Light") }
			if (systemStarted.state != ON && Switch_Hallway_Light.state == ON)					{ awaymessage.append("\n - Switch_Hallway_Light") }
			if (systemStarted.state != ON && Switch_LaundryRoom_Light.state == ON)				{ awaymessage.append("\n - Switch_LaundryRoom_Light") }
			if (systemStarted.state != ON && Switch_MyOffice_Light.state == ON)					{ awaymessage.append("\n - Switch_MyOffice_Light") }
			if (systemStarted.state != ON && Switch_Bathroom_Light.state == ON)					{ awaymessage.append("\n - Switch_Bathroom_Light") }
			if (systemStarted.state != ON && Switch_Gym_Light.state == ON)						{ awaymessage.append("\n - Switch_Gym_Light") }
			if (systemStarted.state != ON && Wallplug_Cubby_Light.state == ON)					{ awaymessage.append("\n - Wallplug_Cubby_Light") }
			if (systemStarted.state != ON && Wallplug_Guest_Air_Cleaner.state == ON)			{ awaymessage.append("\n - Wallplug_Guest_Air_Cleaner") }
			if (systemStarted.state != ON && Wallplug_Bedroom_Air_Cleaner.state == ON)			{ awaymessage.append("\n - Wallplug_Bedroom_Air_Cleaner") }
			if (systemStarted.state != ON && Wallplug_Loft_Air_Cleaner.state == ON)				{ awaymessage.append("\n - Wallplug_Loft_Air_Cleaner") }
			if (systemStarted.state != ON && Wallplug_Jays_Office_Light.state == ON)			{ awaymessage.append("\n - Wallplug_Jays_Office_Light") }
			if (systemStarted.state != ON && Wallplug_Living_Room_Light.state == ON)			{ awaymessage.append("\n - Wallplug_Living_Room_Light") }
			if (systemStarted.state != ON && Wallplug_Loft_Light.state == ON)					{ awaymessage.append("\n - Wallplug_Loft_Light") }
			if (systemStarted.state != ON && Wallplug_Master_Bedroom_Left_Light.state == ON)	{ awaymessage.append("\n - Wallplug_Master_Bedroom_Left_Light") }
			if (systemStarted.state != ON && Wallplug_Master_Bedroom_Right_Light.state == ON)	{ awaymessage.append("\n - Wallplug_Master_Bedroom_Right_Light") }
			if (systemStarted.state != ON && Wallplug_String_Lights.state == ON)				{ awaymessage.append("\n - Wallplug_String_Lights") }
			if (systemStarted.state != ON && Wallplug_xMas_Tree.state == ON)					{ awaymessage.append("\n - Wallplug_xMas_Tree (Salt Rock)") }
			if (systemStarted.state != ON && Wallplug_Loft_Dehumidifier.state == ON)			{ awaymessage.append("\n - Wallplug_Loft_Dehumidifier") }
			if (systemStarted.state != ON && Wallplug_Basement_Dehumidifier.state == ON)		{ awaymessage.append("\n - Wallplug_Basement_Dehumidifier") }
			if (systemStarted.state != ON && Wallplug_MyLamp.state == ON)						{ awaymessage.append("\n - Wallplug_MyLamp (Tricias Lamp)") }
			if (systemStarted.state != ON && Wallplug_TreeLights.state == ON)					{ awaymessage.append("\n - Wallplug_TreeLights") }
			if (systemStarted.state != ON && Wallplug_GrandFather.state == ON)					{ awaymessage.append("\n - Wallplug_GrandFather") }
			if (systemStarted.state != ON && Wallplug_Treadmill.state == ON)					{ awaymessage.append("\n - Wallplug_Treadmill") }
			if (systemStarted.state != ON && Wallplug_Elliptical.state == ON)					{ awaymessage.append("\n - Wallplug_Elliptical") }

			if (systemStarted.state != ON)														{ awaymessage.append("\n \n ------------------------------------------------------------------------ ")}
			if (systemStarted.state != ON)														{ awaymessage.append("\n ** Samsung TVs = ON Now **")}
			if (systemStarted.state != ON)														{ awaymessage.append("\n ------------------------------------------------------------------------ ")}
			if (systemStarted.state != ON && Living_TV_Power.state == ON)						{ awaymessage.append("\n - Living_TV_Power") }
			if (systemStarted.state != ON && Bedroom_TV_Power.state == ON)						{ awaymessage.append("\n - Bedroom_TV_Power") }
			if (systemStarted.state != ON && Basement_TV_Power.state == ON) 					{ awaymessage.append("\n - Basement_TV_Power (Wireless)") }
			if (systemStarted.state != ON && Basement_TV_Wired_Power.state == ON)				{ awaymessage.append("\n - Basement_TV_Wired_Power") }
			if (systemStarted.state != ON && Gym_TV_Power.state == ON)							{ awaymessage.append("\n - Gym_TV_Power") }
			if (systemStarted.state != ON && Parker_TV_Power.state == ON)						{ awaymessage.append("\n - Parker_TV_Power") }
			if (systemStarted.state != ON && Ryan_TV_Power.state == ON) 						{ awaymessage.append("\n - Ryan_TV_Power") }
			if (systemStarted.state != ON && Discover_Living_TV_Power.state == ON)				{ awaymessage.append("\n - Discover_Living_TV_Power") }
			if (systemStarted.state != ON && Discover_Bedroom_TV_Power.state == ON)				{ awaymessage.append("\n - Discover_Bedroom_TV_Power") }
			if (systemStarted.state != ON && Discover_Basement_TV_Wired_Power.state == ON)		{ awaymessage.append("\n - Discover_Basement_TV_Wired_Power") }
			if (systemStarted.state != ON && Discover_Gym_TV_Power.state == ON)					{ awaymessage.append("\n - Discover_Gym_TV_Power") }
			if (systemStarted.state != ON && Discover_Parker_TV_Power.state == ON)				{ awaymessage.append("\n - Discover_Parker_TV_Power") }
			if (systemStarted.state != ON && Discover_Ryan_TV_Power.state == ON) 				{ awaymessage.append("\n - Discover_Ryan_TV_Power") }

			if (systemStarted.state != ON)														{ awaymessage.append("\n \n ------------------------------------------------------------------------ ")}
			if (systemStarted.state != ON)														{ awaymessage.append("\n ** Onkyo Receivers = ON Now **")}
			if (systemStarted.state != ON)														{ awaymessage.append("\n ------------------------------------------------------------------------ ")}
			if (systemStarted.state != ON && OnkyoLRPower.state == ON)							{ awaymessage.append("\n - OnkyoLRPower") }
			if (systemStarted.state != ON && Onkyo_LivingRoom_Power.state == ON)				{ awaymessage.append("\n - Onkyo_LivingRoom_Power") }
			if (systemStarted.state != ON && Basement_Power.state == ON)						{ awaymessage.append("\n - Basement_Power") }
			if (systemStarted.state != ON && Onkyo_Basement_Power.state == ON)					{ awaymessage.append("\n - Onkyo_Basement_Power") }

			if (systemStarted.state != ON)														{ awaymessage.append("\n \n ------------------------------------------------------------------------ ")}
			if (systemStarted.state != ON)														{ awaymessage.append("\n ** HUE Lights = ON Now **")}
			if (systemStarted.state != ON)														{ awaymessage.append("\n ------------------------------------------------------------------------ ")}
			if (systemStarted.state != ON && BookShelf_Switch.state == ON)						{ awaymessage.append("\n - BookShelf_Switch") }
			if (systemStarted.state != ON && KitchenShelf_Switch.state == ON)					{ awaymessage.append("\n - KitchenShelf_Switch") }
			if (systemStarted.state != ON && KitchenIsland_Switch.state == ON)					{ awaymessage.append("\n - KitchenIsland_Switch") }
			if (systemStarted.state != ON && BarLedge_Switch.state == ON)						{ awaymessage.append("\n - BarLedge_Switch") }
			if (systemStarted.state != ON && GuestBedLamp_Switch.state == ON)					{ awaymessage.append("\n - GuestBedLamp_Switch") }
			if (systemStarted.state != ON && BedroomLamp_Switch.state == ON)					{ awaymessage.append("\n - BedroomLamp_Switch") }
			if (systemStarted.state != ON && ParkerLamp_Switch.state == ON)						{ awaymessage.append("\n - ParkerLamp_Switch") }
			if (systemStarted.state != ON && PlayBar1_Switch.state == ON)						{ awaymessage.append("\n - PlayBar1_Switch") }
			if (systemStarted.state != ON && PlayBar2_Switch.state == ON)						{ awaymessage.append("\n - PlayBar2_Switch") }
			if (systemStarted.state != ON && Bloom1_Switch.state == ON)							{ awaymessage.append("\n - Bloom1_Switch") }
			
			if (systemStarted.state != ON)														{ awaymessage.append("\n \n ------------------------------------------------------------------------ ")}
			if (systemStarted.state != ON)														{ awaymessage.append("\n ** Sonos = OFFLINE Now **")}
			if (systemStarted.state != ON)														{ awaymessage.append("\n ------------------------------------------------------------------------ ")}
			if (systemStarted.state != ON && SonosThingGym.toString() != 'ONLINE')				{ awaymessage.append("\n - SonosThingGym") }
			if (systemStarted.state != ON && SonosThingGround.toString() != 'ONLINE')			{ awaymessage.append("\n - SonosThingGround (Offline Nov -  Mar)") }
			if (systemStarted.state != ON && SonosThingJay.toString() != 'ONLINE')  			{ awaymessage.append("\n - SonosThingJay") }
			if (systemStarted.state != ON && SonosThingOnWall.toString() != 'ONLINE')			{ awaymessage.append("\n - SonosThingOnWall (Offline Nov -  Mar)") }
			if (systemStarted.state != ON && SonosThingBasement1R.toString() != 'ONLINE') 		{ awaymessage.append("\n - SonosThingBasement1R") }
			if (systemStarted.state != ON && SonosThingBasement2L.toString() != 'ONLINE')		{ awaymessage.append("\n - SonosThingBasement2L") }
			if (systemStarted.state != ON && SonosThingLR1.toString() != 'ONLINE') 				{ awaymessage.append("\n - SonosThingLR1") }
			if (systemStarted.state != ON && SonosThingLR2.toString() != 'ONLINE')  			{ awaymessage.append("\n - SonosThingLR2") }
			if (systemStarted.state != ON && SonosThingLoft1.toString() != 'ONLINE')  			{ awaymessage.append("\n - SonosThingLoft1") }
			if (systemStarted.state != ON && SonosThingLoft2.toString() != 'ONLINE')			{ awaymessage.append("\n - SonosThingLoft2") }
			if (systemStarted.state != ON && SonosThingRyan.toString() != 'ONLINE') 			{ awaymessage.append("\n - SonosThingRyan") }
			if (systemStarted.state != ON && SonosThingTricia.toString() != 'ONLINE') 			{ awaymessage.append("\n - SonosThingTricia") }
			if (systemStarted.state != ON && SonosThingKitchen.toString() != 'ONLINE') 			{ awaymessage.append("\n - SonosThingKitchen") }
			if (systemStarted.state != ON && SonosThingMB.toString() != 'ONLINE') 				{ awaymessage.append("\n - SonosThingMB") }
			if (systemStarted.state != ON && SonosThingMB2.toString() != 'ONLINE') 				{ awaymessage.append("\n - SonosThingMB2") }

			if (systemStarted.state != ON)														{ awaymessage.append("\n \n ------------------------------------------------------------------------ ")}
			if (systemStarted.state != ON)														{ awaymessage.append("\n ** Sonos = PLAYING Now **")}
			if (systemStarted.state != ON)														{ awaymessage.append("\n ------------------------------------------------------------------------ ")}
			if (systemStarted.state != ON && (Sonos_Gym_State.state == 'PLAYING' || Sonos_Gym_State.state == 'PLAY'))						{ awaymessage.append("\n - Sonos_Gym_State") }
			if (systemStarted.state != ON && (Sonos_JaysOffice_State.state == 'PLAYING' || Sonos_JaysOffice_State.state == 'PLAY'))			{ awaymessage.append("\n - Sonos_JaysOffice_State") }
			if (systemStarted.state != ON && (Sonos_OnWallOutside_State.state == 'PLAYING' || Sonos_OnWallOutside_State.state == 'PLAY'))  	{ awaymessage.append("\n - Sonos_OnWallOutside_State") }
			if (systemStarted.state != ON && (Sonos_BackYard_State.state == 'PLAYING' || Sonos_BackYard_State.state == 'PLAY'))				{ awaymessage.append("\n - Sonos_BackYard_State") }
			if (systemStarted.state != ON && (Sonos_Basement2_State.state == 'PLAYING' || Sonos_Basement2_State.state == 'PLAY')) 			{ awaymessage.append("\n - Sonos_Basement2_State (Master)") }
			if (systemStarted.state != ON && (Sonos_LivingRoom_State.state == 'PLAYING' || Sonos_LivingRoom_State.state == 'PLAY'))			{ awaymessage.append("\n - Sonos_LivingRoom_State (Master)") }
			if (systemStarted.state != ON && (Sonos_Loft2_State.state == 'PLAYING' || Sonos_Loft2_State.state == 'PLAY')) 					{ awaymessage.append("\n - Sonos_Loft2_State (Master)") }
			if (systemStarted.state != ON && (Sonos_TriciasOffice_State.state == 'PLAYING' || Sonos_TriciasOffice_State.state == 'PLAY'))  	{ awaymessage.append("\n - Sonos_TriciasOffice_State") }
			if (systemStarted.state != ON && (Sonos_Kitchen_State.state == 'PLAYING' || Sonos_Kitchen_State.state == 'PLAY'))  				{ awaymessage.append("\n - Sonos_Kitchen_State") }
			if (systemStarted.state != ON && (Sonos_MasterBedroom2_State.state == 'PLAYING' || Sonos_MasterBedroom2_State.state == 'PLAY'))	{ awaymessage.append("\n - Sonos_MasterBedroom2_State (Master)") }
			if (systemStarted.state != ON && (Sonos_RyansRoom_State.state == 'PLAYING' || Sonos_RyansRoom_State.state == 'PLAY')) 			{ awaymessage.append("\n - Sonos_RyansRoom_State") }

			if (systemStarted.state != ON)														{ awaymessage.append("\n \n ------------------------------------------------------------------------ ")}
			if (systemStarted.state != ON)														{ awaymessage.append("\n ** Ceiling Fans = ON Now **")}
			if (systemStarted.state != ON)														{ awaymessage.append("\n ------------------------------------------------------------------------ ")}
			if (systemStarted.state != ON && Office_Fan_Switch.state == ON) 					{ awaymessage.append("\n - Office_Fan_Switch") }
			if (systemStarted.state != ON && Parker_Fan_Switch.state == ON) 					{ awaymessage.append("\n - Parker_Fan_Switch") }
			if (systemStarted.state != ON && Ryan_Fan_Switch.state == ON)						{ awaymessage.append("\n - Ryan_Fan_Switch") }
			if (systemStarted.state != ON && Guest_Fan_Switch.state == ON)						{ awaymessage.append("\n - Guest_Fan_Switch") }
			if (systemStarted.state != ON && Bedroom_Fan_Switch.state == ON)					{ awaymessage.append("\n - Bedroom_Fan_Switch") }

			if (systemStarted.state != ON)														{ awaymessage.append("\n \n ------------------------------------------------------------------------ ")}
			if (systemStarted.state != ON)														{ awaymessage.append("\n ** Ceiling Fan Lights = ON Now **")}
			if (systemStarted.state != ON)														{ awaymessage.append("\n ------------------------------------------------------------------------ ")}
			if (systemStarted.state != ON && Office_CeilingLight_Switch.state == ON)			{ awaymessage.append("\n - Office_CeilingLight_Switch") }
			if (systemStarted.state != ON && Parker_CeilingLight_Switch.state == ON)			{ awaymessage.append("\n - Parker_CeilingLight_Switch") }
			if (systemStarted.state != ON && Ryan_CeilingLight_Switch.state == ON)				{ awaymessage.append("\n - Ryan_CeilingLight_Switch") }
			if (systemStarted.state != ON && Guest_CeilingLight_Switch.state == ON) 			{ awaymessage.append("\n - Guest_CeilingLight_Switch") }
			if (systemStarted.state != ON && Bedroom_CeilingLight_Switch.state == ON)			{ awaymessage.append("\n - Bedroom_CeilingLight_Switch") }

			if (systemStarted.state != ON)														{ awaymessage.append("\n \n ------------------------------------------------------------------------ ")}
			if (systemStarted.state != ON)														{ awaymessage.append("\n ** zWave Temps Now **")}
			if (systemStarted.state != ON)														{ awaymessage.append("\n ------------------------------------------------------------------------ ")}
			if (systemStarted.state != ON)														{ awaymessage.append("\n - FurnaceSensor_Temp is " + FurnaceSensor_Temp.state) }
			if (systemStarted.state != ON)														{ awaymessage.append("\n - SumpPumpSensor_Temp is " + SumpPumpSensor_Temp.state) }
			if (systemStarted.state != ON) 														{ awaymessage.append("\n - LaundrySensor_Temp is " + LaundrySensor_Temp.state) }
			if (systemStarted.state != ON)														{ awaymessage.append("\n - FoyerSensor_Temp is " + FoyerSensor_Temp.state) }
			if (systemStarted.state != ON)														{ awaymessage.append("\n - BasementSensor_Temp is " + BasementSensor_Temp.state) }
			if (systemStarted.state != ON)														{ awaymessage.append("\n - LoftSensor_Temp is " + LoftSensor_Temp.state) }
			if (systemStarted.state != ON) 														{ awaymessage.append("\n - GarageSensor_Temp is " + GarageSensor_Temp.state) }
			if (systemStarted.state != ON) 														{ awaymessage.append("\n - AtticSensor_Temp is " + AtticSensor_Temp.state) }
			if (systemStarted.state != ON) 														{ awaymessage.append("\n - KitchenSensor_Temp is " + KitchenSensor_Temp.state) }

			if (systemStarted.state != ON)														{ awaymessage.append("\n \n ------------------------------------------------------------------------ ")}
			if (systemStarted.state != ON)														{ awaymessage.append("\n ** Ecobee States **")}
			if (systemStarted.state != ON)														{ awaymessage.append("\n ------------------------------------------------------------------------ ")}
			if (systemStarted.state != ON)														{ awaymessage.append("\n - MF_settings_hvacMode.state is " + MF_settings_hvacMode.state) }
			if (systemStarted.state != ON)														{ awaymessage.append("\n - MF_settings_fanMinOnTime.state is " + MF_settings_fanMinOnTime.state) }
			if (systemStarted.state != ON)														{ awaymessage.append("\n - MF_runningEvent_climate.state is " + MF_runningEvent_climate.state) }
			if (systemStarted.state != ON)														{ awaymessage.append("\n - MF_runtime_actualTemperature.state is " + MF_runtime_actualTemperature.state + " F") }

			if (systemStarted.state != ON)														{ awaymessage.append("\n - UpS_settings_hvacMode.state is " + UpS_settings_hvacMode.state) }
			if (systemStarted.state != ON)														{ awaymessage.append("\n - UpS_settings_fanMinOnTime.state is " + UpS_settings_fanMinOnTime.state) }
			if (systemStarted.state != ON)														{ awaymessage.append("\n - UpS_runningEvent_climate.state is " + UpS_runningEvent_climate.state) }
			if (systemStarted.state != ON)														{ awaymessage.append("\n - UpS_runtime_actualTemperature.state is " + UpS_runtime_actualTemperature.state + " F") }
			
			if (systemStarted.state != ON)														{ awaymessage.append("\n \n ------------------------------------------------------------------------ ")}
			if (systemStarted.state != ON)														{ awaymessage.append("\n ** zWave Humidity Now **")}
			if (systemStarted.state != ON)														{ awaymessage.append("\n ------------------------------------------------------------------------ ")}
			if (systemStarted.state != ON)														{ awaymessage.append("\n - FoyerSensor_Humidity is " + FoyerSensor_Humidity.state + "%") }
			if (systemStarted.state != ON)														{ awaymessage.append("\n - BasementSensor_Humidity is " + BasementSensor_Humidity.state + "%") }
			if (systemStarted.state != ON)														{ awaymessage.append("\n - LoftSensor_Humidity is " + LoftSensor_Humidity.state + "%") }
			if (systemStarted.state != ON) 														{ awaymessage.append("\n - GarageSensor_Humidity is " + GarageSensor_Humidity.state + "%") }
			if (systemStarted.state != ON) 														{ awaymessage.append("\n - AtticSensor_Humidity is " + AtticSensor_Humidity.state + "%") }
			if (systemStarted.state != ON) 														{ awaymessage.append("\n - KitchenSensor_Humidity is " + KitchenSensor_Humidity.state + "%") }

			if (systemStarted.state != ON)														{ awaymessage.append("\n \n ------------------------------------------------------------------------ ")}
			if (systemStarted.state != ON)														{ awaymessage.append("\n ** PS/4 = ON Now **")}
			if (systemStarted.state != ON)														{ awaymessage.append("\n ------------------------------------------------------------------------ ")}
			if (systemStarted.state != ON && PS4Basement.state == ON)							{ awaymessage.append("\n - PS4Basement (Wired)") }
			if (systemStarted.state != ON && PS4BasementWireless.state == ON)					{ awaymessage.append("\n - PS4BasementWireless") }

			if (systemStarted.state != ON)														{ awaymessage.append("\n \n ------------------------------------------------------------------------ ")}
			if (systemStarted.state != ON)														{ awaymessage.append("\n ** End of Report ** \n") }
			
			var String subjectawayemail = "openHAB - Home Away Report"	
	
			sendMail(JaygMail, subjectawayemail, awaymessage.toString())
				Thread::sleep(200)  

			logInfo("eMail", "Home Away eMail Report Sent to JaygMail.")
			
			Away_Report.postUpdate(OFF) 
		}
end		

Best, Jay