Driver Preferences - store long strings

Hi,

I have a requirement to be able to store a long string in a driver preference.. specifically the below for an IR driver, unfortunately this is how a raw command looks and this value needs to be passed in a post request.. I've tried text / string both return a 500 error when I try to save the full length string..

Are there any options available, other than passing to a parent app?

8990,4500,556,1688,604,514,578,542,578,560,556,562,556,560,612,508,578,562,556,562,556,1688,602,1640,580,1700,544,1688,556,1686,556,1688,576,1670,578,1688,554,1686,554,562,582,538,580,560,556,560,556,562,604,514,576,576,546,560,558,1686,554,1688,576,1668,580,1686,556,1688,556,1688,576,1692,554,1664,578,562,554,562,556,560,556,564,578,560,556,560,556,562,582,562,556,1686,556,1686,554,1686,530,1712,554,1690,580,1684,556,13496,8986,2248,556

Take a look at my send IP2IR app. Feel free to use any parts that you like in your undertaking.

Have fun!

2 Likes

TBH I'm fine with the code side, there are two types of code accepted in my application, a short code if recognised, from TVs etc.. but for other devices I need a raw code.. mines using an ESP8266 so only costs a couple of $/£ per transmitter.. just need to work out if I can store the raw string in the driver, if I can it makes the whole thing very simple, if not then I will need to port over my app from ST, which is just much more clunky than doing it in the driver :slight_smile:

1 Like

just store them in a state variable, if need be just make the state var a map, then use the key in this map to driver the preference settings...

Thanks mike, the raw IR command I provided was an example, it could be any configurable long string and of values so need some way to specify in the driver settings.. unless I'm misunderstanding your suggestion.. I don't think it's possible with the current driver field limitations?

When I developed the Alexa TTS integration for Hubitat, I also had an issue with a very long string (a cookie) that the user would supply. Due to the length limitation, I implemented it as a Parent App that created Child Devices. This works well because users often have multiple Amazon Echo devices. I simply let the Parent App handle all of the network communications since it can handle very long strings as a setting.

You can look at my code to see how I did it, although it sounds like you faced the same issue on ST already and may have a design that could be ported to Hubitat...

1 Like

Yeah, I did a similar thing in ST, I was hoping the limitation would disappear in HE as its just a bit clunky and would avoid app usage entirely, but guess I'll need to do similar here..

right, so:
state.ir = [1:hexCodesForCommand1, 2:hexCodesForCommand2.....]

input irSelect...., options:[[1:"display text for ir codes 1"],[ 2:"display text for ir code 2"], ....]

1 Like

I understood what you meant using maps and state variables, it's just getting the variables in to the instance of the driver without an app to inject them in to states..

command addIRCode, ["STRING"]
or maybe ["NUMBER", "STRING"] if you want the user to enter the map key as well
or even ["NUMBER", "STRING", "STRING"] where addIrCode(mapKey, IRCode, displayName)
all depends on how crazy you want to get with it

2 Likes

I think I see what you mean, I'll give it a go in the morning as getting late here in the uk

Hi Mike,

This is working perfectly thanks, just needed to enclose addIRCode in speech marks..

For the command field can you set default values, and is there any way to set the order, "On" and "Off" are appearing after the set commands? Neither are a big issue if not.. just thought I'd check?

Code for reference below in case anyone has a similar issue..

metadata {
	definition (name: "IR Device", namespace: "jebbett", author: "Jake Tebbett") {
		
		capability "Switch"
		capability "Momentary"
		capability "Actuator"
		command "SetRawOn", ["STRING"]
		command "SetRawOff", ["STRING"]
	}
}

preferences {
	input("IRtype", "enum", title:"Type", required:true, displayDuringSetup:true, options: ["CODE", "RAW"])
    input("cmdOn", "text", title:"Command On", required:false, displayDuringSetup:true, defaultValue: "E0E040BF:SAMSUNG:32")
    input("cmdOff", "text", title:"Command Off", required:false, displayDuringSetup:true, defaultValue: "E0E040BF:SAMSUNG:32")
    input("ipAddr", "text", title:"IP Address", required:true, displayDuringSetup:true, defaultValue: "192.168.1.240")
    input("port", "string", title:"Port", required:true, displayDuringSetup:true, defaultValue: "80")
    input("pwd", "password", title:"Password", required:true, displayDuringSetup:true, defaultValue: "password")
}

private sendIR(command){
	def thisPath = "http://" + settings.ipAddr +":" +settings.port
	
	if(settings.IRtype == "CODE"){
		thisPath += "/msg?code=" + command + "&simple=1&pass=" + settings.pwd
	}else{
		thisPath += "/json?plain=%5B%7B%27data%27:%5B" + command + "%5D,%27type%27:%27raw%27,%27khz%27:38%7D%5D&simple=1&pass=" + settings.pwd
		// NOTE ASCII code conversion: %5B = [, %5D = ], %7B = {, %7D = }, %27 = '
	}

	def postParams = [
		uri: thisPath,
        headers: ["contentType": "text/plain"]
	]
	try {
        httpPost(postParams) { resp ->
            log.debug resp.data
        }
    } catch(Exception e) {
        log.debug "error occured calling httpPost ${e}"
    }
}

def push() {
	sendEvent(name: "switch", value: "on", isStateChange: true, displayed: false)
	sendEvent(name: "switch", value: "off", isStateChange: true, displayed: false)
	sendEvent(name: "momentary", value: "pushed", isStateChange: true)
	if(settings.IRtype == "CODE"){ sendIR(settings.cmdOn) }else{ sendIR(state.rawIrOn) }
}

def on() {
	push()
}

def off() {
	if(settings.IRtype == "CODE"){ sendIR(settings.cmdOff) }else{ sendIR(state.rawIrOff) }
}

def SetRawOn(IRCode){
	state.rawIrOn = IRCode
}
def SetRawOff(IRCode){
	state.rawIrOff = IRCode
}

These are the little devices the driver controls:

5 Likes

@jebbett and @mike.maxwell - Thank you for sharing this workaround for long string data entry into a driver. Very helpful.

1 Like

sure:
def someCommand(value = defaultValue) {bla bla}
then a call to someCommand() will use the default, and someCommand(someOtherValue) does what it says on the tin

Is there a way for a list in a driver command to SHOW the default value in the dropdown box by default - instead of just the first list entry?

I'm assuming not since none of the built-in drivers that I've seen do that either.

Example - for my Remotec ZTS-500 driver, there is a Sensor Cal command. Dropdown list of values for the command are -10 to +10, default is ZERO. It would be super if the dropdown box showed ZERO instead of -10 (the first item in the list).

I guess I could always just re-do the list making the default the first value, but what fun is that - everything will be out of order?

Sorry I probably wasn't clear, I meant for the line below, can there be a default value specified, so when viewed in the browser the string field has a value presented? I have seen it in the hue driver I believe, unless that is achieved differently?

command "SetRawOn", ["STRING"]

@JasonJoelOld, you just need to specify the default value? If using a list with keys and values then you need to specify the key as the default value.. there is an example on the HE GitHub for the generic RGB bulb

, defaultValue: 1

I've tried that a few times, and it doesn't seem to do anything. Maybe my syntax is wrong?

command "SensorCal", [[name:"calibration",type:"ENUM", description:"Number of degrees to add/substract from thermostat sensor", defaultValue: "0", constraints:["-10", "-9", "-8", "-7", "-6", "-5", "-4", "-3", "-2", "-1", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10"]]]

Which still yields this in the combo box:
21%20AM

1 Like

Commands do not have the same level of option support and functionality that input preferences do.
They may in the future, but the primary goal of the extended command definition schema was simply to offer help with command parameter descriptions.

2 Likes

Thanks for clarifying - that is actually what I assumed after trying it.

No worries, either. Functionally everything is great - it is really just for aesthetics it would be nice to show the default value selected in the drop down. Very low priority in terms of competing with other development needs.