Some programming help please!

I'm embarrassed to ask this - I can't seem to get a comparator to work.

I've built a driver and I have a string to store the current Month.
attribute "todaysFormattedMonth", "string"

sendEvent(name: "todaysFormattedMonth", value : proposedFormattedMonth)

The displayed value is perfect.
I now want to compare it to 1 text string. (I'm not ready to learn arrays so hold off on advanced dialog for now please)

I write but get a false response for
if ("${todaysFormattedMonth}" == ("October")) {

I've studied the groovy manuals, java manuals and I'm not understanding! what am I doing wrong?!?!

This is the problem. You want to reference the todaysFormattedMonth attribute. Device attributes do not automatically become fields/properties/etc. (at least not with their exact name) in Hubitat drivers. so just referencing todaysFormattedMonth somewhere doesn't mean anything. The most common way of accessing what you what would be the currentValue() method (docs here), like:

device.currentValue("todaysFormattedMonth")

(You may also see "lastValue" instead of "currentValue," which is not documented but is likely the exact same and is probably included for SmartThings compatibility.)

You might notice some vague phrasing above. :slight_smile: That's because it actually does become a property:

device.currentTodaysFormattedMonth

All device attributes become properties with this naming convention. However, I like the (more common?) currentValue() method myself, and that's what you'll see in most example code, so I prefer to follow suit.

2 Likes

In addition to the excellent advice provided above by @bertabcd1234...

Just in case you missed this detail, you'll also want to make sure that you declare the custom attribute "todaysFormattedMonth" in the driver. Otherwise, it will not persistently show on the device details page, and other apps will not be able to reference it.

If no apps need to reference this piece of data (i.e. it is internal only to the driver), you could also store it in 'state', instead of as an attribute, and thus not need to use sendEvent() calls.

    state.todaysFormattedMonth = proposedFormattedMonth

and then

    if (state.todaysFormattedMonth == "October") {
    }
2 Likes

I'm very grateful! in the span of minutes it seems you solved my problem! I wrote:
if (device.currentValue("todaysFormattedMonth") == ("October")) {
fall()
} else {
sendEvent(name: "rawDate", value : rawdate,descriptionText: descriptionText)
sendEvent(name: "seasonName", value: "Not Initialized",descriptionText: descriptionText)
sendEvent(name: "seasonNum", value: 5,descriptionText: descriptionText)

and got a True response, tried it again with a forced typo and got a false! I spent 3 hours on that ... :slight_smile: thank you!

3 Likes

I hadn't learned that far ahead yet - but it is my intent to use the values (potentially) in rules down the road. I'm guessing this applies to that as well.
Thanks for the additional knowledge !

Success! (A lot to cleanup but:
image

3 Likes

There may be some cross-over here between this and another thread:

Depending on how you're code is achieving the detection of the seasons, there may be some useful information on both threads. I mentioned on the linked thread about the potential for using something like a Google Calendar and switches to drive automations like this, but depends on your use case.

Simon

I am following that thread - and lots of similarity sure. In my case, you all answered it with use of rules. I succeeded with it that way but wasn't completely satisfied so I started down this new path of creating a driver -
I began with a modeling from MoonPhase by @thebearmay which taught me a ton, then I snagged pieces from the DateFormat from @sburke781 and @luarmr. Then there was the foundational stuff I learned by stealing from the Onmi driver assumedly @bravenel created for masses...

It is even by my standards ugly, badly written and in(un?)elegant. It was working great until a few minutes ago when I started adding the calcSeason so as to allow a quick method to see a season for a given date. But it's been super fun!
Isaac Newton in 1675: "If I have seen further it is by standing on the shoulders of Giants."[3]

3 Likes

Glad you got something from the date formatting driver. And that's exactly what I did, used other driver's as examples and just kept writing, learning so much along the way, also writing some ugly code, still do :wink: It is nice when something come's together like this.

uh... more help?!

In my driver I have 'inputs' under preferences.. so they appear on the page and allow input. However I'm trying to clean them up - they aren't variable per se.

I want to take this line and comment it out (I know how!!!) :
input(name: "dateFormat", type: "string", title:"Date Format", description: "Enter the date format to apply for display purposes", defaultValue: "MM-dd-yyyy", required: true, displayDuringSetup: true)

and place a hard set value to the dateFormat.
I tried dateFormat(yyyy-MM-dd) but I've discovered that is what broke my driver.

I tried def dateFormat = new SimpleDateFormat("MM-dd-yyyy")
but my IDE says 'cannot assign SimpleDateFormat to object
I tried def dateFormat = new SimpleDateFormat("MM-dd-yyyy") as java.lang.Object
but my IDE says 'assignment not used'

I simply want to store in the dateFormat() to hard value so it's hidden from the interface, but still functional within my driver. is this one of those device.dateFormat things?

To be honest, I am experienced in different languages but not on java.
But probably SimpleDateFormat dateFormat = new SimpleDateFormat("MM-dd-yyyy"); is what you are looking for.

1 Like

Changing the value of an “input” requires a call to device.updateSetting(), but you could do something like:

import groovy.transform.Field
@Field defDate 

….
SimpleDateFormat sdf= new SimpleDateFormat("yyyy-MM-dd")  
defDate = sdf.format(now())
input(name: "dateFormat", type: "string", title:"Date Format", description: "Enter the date format to apply for display purposes", defaultValue: defDate, required: true, displayDuringSetup: true


1 Like

It does depend on whether you still want the ability to still adjust the format after starting with a default value, or whether you want the Preference setting gone altogether. If you want the ability to update the format used then @thebearmay 's example will allow you to do that.

If you want to simply store the fixed date format string for use throughout the driver, then you could store that in the state data (probably no need to have it in an attribute):

state.dateFormatString = "MM-dd-yyyy"

Then wherever you want to use it, the process should be almost the same as in my driver:

simpleDateFormatForDate = new java.text.SimpleDateFormat(state.dateFormatString);

I'll have to check, but can only imagine java.text.SimpleDateFormat must not be loaded by default, which was why I had to refer to the full package path...

True will need an

import java.text.SimpleDateFormat

at the beginning of the code

1 Like

Many gracious thanks gentlemen -
I tried the suggestion you've all made to the best of my pathetic abilities - and never quite succeeded - UNTIL... (I had the import call, and tried redefining as described but it just kept aloof)

I took the values I wanted hardset straight to the definition source. Here is my change to the stolen source that ended up working. It always is so simple AFTER you get it! (the input line is now commented out:
def runCmd() {
now = new Date()
//simpleDateFormatForDate = new SimpleDateFormat(dateFormat)
simpleDateFormatForDate = new SimpleDateFormat('dd-MM-yyyy')

now back to cleaning my work (which caused this in the first place! HA no doubt I'll be back as Arnold says.)

2 Likes