Persisting Variable

I have read over and over but can’t seem to come up with a solution. I know why it is functioning the way it is but I cannot figure out how to make it function the way I want.

I am trying to create a map of energy monitor readings. Ideally every time the DTH gets information from the unit it would add to the map. Right now because I have to define the map in the method it is continuously overwriting versus adding. Where can I define the map so that it persists (I know, persisting variables are not really a thing in ST) but I imagine someone has cracked this nut without going outside to something like a google doc.

def zwaveEvent(physicalgraph.zwave.commands.meterv1.MeterReport cmd) {

def dispValue
def newValue
def newPowerValue
def timeString = new Date()

def countCheck
  	def energyEvent = [:]
def energyData = [:]

	if (cmd.scale == 0) {	
    newValue = cmd.scaledMeterValue
    [name: "energy", value: cmd.scaledMeterValue, unit: "kWh"]
    dispValue = String.format("%5.2f",newValue)
    sendEvent(name: "energy", value: dispValue as String, unit: "kWh")
    state.energyValue = newValue
    BigDecimal costDecimal = newValue * ( kWhCost as BigDecimal)
    def costDisplay = String.format("%5.2f",costDecimal)
    sendEvent(name: "energyCost", value: "\$${costDisplay}", unit: "", displayed: false)
//Energy Trending
    energyEvent.date = timeString.format("HH:MM", location.timeZone)
    energyEvent.energy = newValue
    energyData << energyEvent
    log.debug "${energyEvent} added to energy trend"
    countCheck = energyData.size()
    log.debug "${countCheck} items in countCheck"
}
else if (cmd.scale == 1) {
    [name: "energy", value: cmd.scaledMeterValue, unit: "kVAh"]
}

Have a look at using “state” which is the persistent data store that SmartThings makes available to DTH’s & SmartApps. There are limits in terms of how much data you can store, 100KB when serialized to a JSON string.

http://docs.smartthings.com/en/latest/smartapp-developers-guide/state.html

If you’re looking to store a history of power readings the interval in which you add values will directly determine how much history you can have. Curious as to why you’re storing kWH values as those will always be incrementing.

If I were you, I would break this into a DTH for capturing the power values, but put the actual logging into a SmartApp. This will allow you to use other means for storing data. For example, there is user submitted code around here for storing power readings in a Google docs spreadsheet.

Thanks. I stumbled upon converting maps to strings and strings back to maps so I can use state to store. Only reason I am working on kWh is because the DTH is setup to get information back more frequently so I am doing it for testing purposes. I will instead be converting the code to store power once I get things figured out.

I am close at this point but am having trouble converting the string back to a map.
The code I found is throwing an error:

def map =
    // Take the String value between
    // the [ and ] brackets.
    mapAsString[1..-2]
        // Split on , to get a List.
        .split(', ')
        // Each list item is transformed
        // to a Map entry with key/value.
        .collectEntries { entry ->
            def pair = entry.split(':')
            [(pair.first()): pair.last()]
        }

You don’t need to convert maps to text to use in state. You can store a map in state. You cannot store objects like devices, but maps you can.

Here’s a very rough example…

state.maptest = [:]
def mapData = [
    SomeKey:  SomeValue,
    AnotherKey: AnotherValue
]

state.maptest.put(“recordKey”, mapData)

You can pull data back out as you would any map.

This is what I initially tried but assuming because initially defining state.maptest = [:], every time I would run through the process to add another value there would only be one value in the map.

Make sure you’re using the put() function and not the << operator to add the already defined map.

Using put() I am getting the error: “java.lang.NullPointerException: Cannot invoke method put() on null object”

EDIT: played around a little and I think I got it. Thank you for your help.