errorgroovy.lang.MissingMethodException: No signature of method: java.io.StringReader.split() is applicable for argument types: (java.lang.String) values: Possible solutions: split(groovy.lang.Closure), wait(), wait(long), skip(long), skip(long), getAt(java.lang.String) on line 26 (refresh)
metadata {
definition(
name: "Test",
namespace: "Test",
author: "Test")
{
capability "Refresh"
}
}
def refresh() { (sendSyncCmd()) }
private sendSyncCmd() {
def host = "http://192.168.1.157"
def command = "/Blind/ID=2/level=0"
def responseMap = [:]
httpGet([uri: "${host}${command}",
contentType: "text/plain",
textParser: true])
{ response ->
def data = response.getData().toString()
log.info "data: ${data}" //shows the full response in the log
//if response.data didn't print the entire response then change this to getData() or something that did.
//
data.split("\r").each {
def parts = it.split(":")
responseMap[parts[0].trim()] = parts[1].trim()
}
}
//assuming everything went right up to this point you should be able to do...
//if it didn't go correctly we probably know that the new line character is something other than "\r" and we'll try "\n" or "\r\n"
log.debug "value of Battery is ${responseMap.Battery}"
log.debug "value of Voltage is ${responseMap.Voltage}"
}
Is the full response still printing from that log.info? If so, do you have a link to the project that you used for the Arduino or the snippet of code that built the response? We need to know what the new lines are. And the problem is you can't really copy and paste them because they are probably changed in the log. I'm too lazy to show you how to print out the int character value. We'll do that if you don't have the code that generated that response. This one.
//Prepare response
String s = "HTTP/1.1 200 OK\r\n";
s += "Content-Type: text/html\r\n\r\n";
s += "<!DOCTYPE HTML>\r\n<html>\r\n";
s += "Blind ID: ";
s += blindID;
s += "<br>";
s += "Group: Null<br>";
s += "Level: ";
s += level;
s += "<br>";
s += "Battery: ";
s += myPacket->percent;
s += "<br>Voltage: ";
s += voltage;
s += "<br>Charger: ";
s += myPacket->charger;
s += "<br>Success.<br>";
No go, screenshot below... also I don't know if it's of any consequence but I screenshot'ed to show that there's a blank line at the first of the data...
And here's a full copy of this driver now , just to confirm:
metadata {
definition(
name: "Test",
namespace: "Test",
author: "Test")
{
capability "Refresh"
}
}
def refresh() { (sendSyncCmd()) }
private sendSyncCmd() {
def host = "http://192.168.1.157"
def command = "/Blind/ID=2/level=0"
def responseMap = [:]
httpGet([uri: "${host}${command}",
contentType: "text/plain",
textParser: true])
{ response ->
log.info "data: ${response.getData()}" //shows the full response in the log
//if response.data didn't print the entire response then change this to getData() or something that did.
//
data.split("<br>").each {
if (it.contains(":")) {
def parts = it.split(":")
responseMap[parts[0].trim()] = parts[1].trim()
}
}
}
//assuming everything went right up to this point you should be able to do...
//if it didn't go correctly we probably know that the new line character is something other than "\r" and we'll try "\n" or "\r\n"
log.debug "value of Battery is ${responseMap.Battery}"
log.debug "value of Voltage is ${responseMap.Voltage}"
}
Too manual for my tastes. Let's output some debugging to see what's in our variables.
metadata {
definition(
name: "Test",
namespace: "Test",
author: "Test")
{
capability "Refresh"
}
}
def refresh() { (sendSyncCmd()) }
private sendSyncCmd() {
def host = "http://192.168.1.157"
def command = "/Blind/ID=2/level=0"
def responseMap = [:]
httpGet([uri: "${host}${command}",
contentType: "text/plain",
textParser: true])
{ response ->
log.info "data: ${response.getData()}" //shows the full response in the log
//if response.data didn't print the entire response then change this to getData() or something that did.
log.debug "if we split on <br> there are ${data.split("<br>").length} elements"
log.debug "the first is ${data.split("<br>")[0]}"
data.split("<br>").each {
//tmp output
log.debug "working on \"${it}\""
if (it.contains(":")) {
def parts = it.split(":")
responseMap[parts[0].trim()] = parts[1].trim()
}
}
}
//assuming everything went right up to this point you should be able to do...
//if it didn't go correctly we probably know that the new line character is something other than "\r" and we'll try "\n" or "\r\n"
log.debug "value of Battery is ${responseMap.Battery}"
log.debug "value of Voltage is ${responseMap.Voltage}"
}
*edit: Oh, maybe I see it. At some point you removed def data = response.getData().toString()
Try this:
metadata {
definition(
name: "Test",
namespace: "Test",
author: "Test")
{
capability "Refresh"
}
}
def refresh() { (sendSyncCmd()) }
private sendSyncCmd() {
def host = "http://192.168.1.157"
def command = "/Blind/ID=2/level=0"
def responseMap = [:]
httpGet([uri: "${host}${command}",
contentType: "text/plain",
textParser: true])
{ response ->
log.info "data: ${response.getData()}" //shows the full response in the log
def data = response.getData().toString()
log.info "data: ${data}" //should still show full response
log.debug "if we split on <br> there are ${data.split("<br>").length} elements"
log.debug "the first is ${data.split("<br>")[0]}"
data.split("<br>").each {
//tmp output
log.debug "working on \"${it}\""
if (it.contains(":")) {
def parts = it.split(":")
responseMap[parts[0].trim()] = parts[1].trim()
}
}
}
//assuming everything went right up to this point you should be able to do...
//if it didn't go correctly we probably know that the new line character is something other than "\r" and we'll try "\n" or "\r\n"
log.debug "value of Battery is ${responseMap.Battery}"
log.debug "value of Voltage is ${responseMap.Voltage}"
}
I'll be in and out all day so responses will be scattered.
So, that's interesting. Apparently GStringImpl doesn't convert objects to String always with the toString method. It must be looking at the StringReader and converting it without toString().
Try this:
metadata {
definition(
name: "Test",
namespace: "Test",
author: "Test")
{
capability "Refresh"
}
}
def refresh() { (sendSyncCmd()) }
private sendSyncCmd() {
def host = "http://192.168.1.157"
def command = "/Blind/ID=2/level=0"
def responseMap = [:]
httpGet([uri: "${host}${command}",
contentType: "text/plain",
textParser: true])
{ response ->
log.info "data: ${response.getData()}" //shows the full response in the log
def data = "${response.getData()}"
log.info "data: ${data}" //should still show full response
log.debug "if we split on <br> there are ${data.split("<br>").length} elements"
log.debug "the first is ${data.split("<br>")[0]}"
data.split("<br>").each {
//tmp output
log.debug "working on \"${it}\""
if (it.contains(":")) {
def parts = it.split(":")
responseMap[parts[0].trim()] = parts[1].trim()
}
}
}
//assuming everything went right up to this point you should be able to do...
//if it didn't go correctly we probably know that the new line character is something other than "\r" and we'll try "\n" or "\r\n"
log.debug "value of Battery is ${responseMap.Battery}"
log.debug "value of Voltage is ${responseMap.Voltage}"
}
I'm going to PM you from here on out. We'll join back here once we have working code. Debugging can be messy when you're doing it on Hubitat through another person.
By the way, here was the result of the PMs. I'm putting it here in case it has any historical significance or helps anybody down the road.
A few key notes:
java.io.StringReader is a stream from the actual server response. You can read from it once. Second time is exception. I should have known that as it is in java.io afterall.
By passing different content types to the httpGet you are changing how the response is parsed. If you pass no content type or plain text the HTML can be stripped from the response. In this case, we didn't want it because we needed the line breaks to split on.
GStringImpl doesn't always call toString apparently on objects inside escape brackets. It knew to use the StringReader appropriately. However, it didn't know to store the result for reuse. The first time "data: ${response.getData()}" was logged it work. The second time it failed. The final solution was to force the GStringImpl to a String and then work with that.
So, it turned out to be a little trickier than anticipated because of the format of the response.
metadata {
definition(
name: "Test",
namespace: "Test",
author: "Test")
{
capability "Refresh"
capability "Battery"
attribute "voltage", "number"
}
}
def refresh() { (sendSyncCmd()) }
private sendSyncCmd() {
def host = "http://192.168.1.157"
def command = "/Blind/ID=2/level=0"
def responseMap = [:]
httpGet([
uri: "${host}${command}",
contentType: "text/plain"
])
{ response ->
def data = "${response.getData()}".toString()
data.split("<br>").each {
if (it.contains(":")) {
def parts = it.split(":")
responseMap[parts[0].trim()] = parts[1].trim()
}
}
}
//assuming everything went right up to this point you should be able to do...
//if it didn't go correctly we probably know that the new line character is something other than "\r" and we'll try "\n" or "\r\n"
log.debug "value of Battery is ${responseMap.Battery}"
log.debug "value of Voltage is ${responseMap.Voltage}"
def battery = responseMap.Battery?.toInteger() ?: 0
battery = battery > 100 ? 100 : battery
battery = battery < 0 ? 0 : battery
sendEvent([name: "battery", value: battery])
sendEvent([name: "voltage", value: new Double(responseMap.Voltage.trim() ?: "0")])
}