Convert String to Number item

Hi!

How could I change this string to number?

temp=49.8’C

I can not do it :frowning:

        val str1 = String::Raspilla_Temp.state.replace('temp=','')
        val str2 = String::str1.replace("'C",'')
        Sensor_Raspilla2_Temp.postUpdate(Float::parseFloat(str2))

Thank you!

Hi

I had a similar issue…

I did discover that in PaperUI, when setting up a temperature, the Item that is create is a Number/Temperature
Which seems to add the °x part.

I just removed the Temperature part :slight_smile:

I’ll add it back in within the UI if I want it again :slight_smile:

I hope that helps you

Maybe you can use the split command?

Here is a rule, to read out my power meter. There i get a long string and with this rule i cut out the needed parts…

rule "power meter 0"
	when
		Time cron "0/30 * * * * ?" // this one cycles every 30 seconds. depends on your needs
	then

		var String meter_payload = executeCommandLine("/usr/src/sml_server /dev/lesekopf0",5000) // note the argument /dev/ttyUSB0 - your meter-device-id goes here 

		val lines = meter_payload.split('\n')

		if (lines.size('\n') > 3) { 
				val counterStr = lines.get(0).split('#').get(1)
				val supplyStr = lines.get(1).split('#').get(1)
				val consumptionStr = lines.get(4).split('#').get(1)

				// Updating the items
				// if (stromzaehler0_bezug.state != counterStr)
				stromzaehler0_bezug.sendCommand(counterStr)
				stromzaehler0_einspeisung.postUpdate(supplyStr)
				stromzaehler0_leistung.postUpdate(consumptionStr)
		}
end

Your rule has to be someting like this… (not tested, only short writing…)

rule "split temp string"
	when
		--- put your arguments here --- maybe "Raspilla_Temp received update"
	then

		var String temp_1 = Raspilla_Temp.state
		val lines1 = string_temp_1.split('#')
		val str1 = lines1.get(1)

                val lines2 = str1.split('\n')
                val str2 = lines2.get(0)	

		// Updating the item
		Sensor_Raspilla2_Temp.postUpdate(str2)
end

Is your temp string item with a space behind the value or is this this sign before the “C”? --> ’

My rule splits the value at the space, when you want to split it at the ’ — you maybe have to use (’’’) instead of (’/n’) but i don´t know, if this works…

1 Like

You should be able to do it mostly the way you are trying to do it. You just have some type and method call weirdness in the syntax you are trying to use.

First of all

 val str1 = String::Raspilla_Temp.state.replace('temp=','')

This line is almost pure nonsense and you should be seeing errors in the log (even better in VSCode as well). What this means in English is: Get the static member of the Class String called Raspilla_Temp, call it’s state method, then call the replace method to replace “temp=” with empty string. Assign the result to str1.

Problems:

  • String has no static member called Raspilla_Temp
  • State has no method called replace

The correct line for what you are trying to do is:

val str1 = Raspilla_Temp.state.toString.replace("temp=","").replace("'C","")

Note I chained the replace calls to get rid of both parts of the String on one line.

Next, you don’t need to parse the String before you pass it to postUpdate. That is already handled for you. So

Sensor_Raspilla2_Temp.postUpdate(str1)

I’m not certain that postUpdate will accept a primitive float like the result of Float::parseFloat. Should you ever need to parse a number from a String like this in a Rule, it’s better to use new Float(str1).

I highly recommend VSCode with the openHAB extension. It will tell you that that line is wrong and what is wrong with them

2 Likes

Hi, just an idea.

Is it possible to cast String into Number in channel?
I have Thing with property of type String and want to connect it with Item of type Number
openhabRaspTemp

ps: Content of that String output is Number, I applied transform for that Exec Command - REGEX(temp=([\d.]*)'C)

Unfortunately no. The item must be of the expected type. You can set up proxy item and rule but you can only link a String item to that channel.

Is there feature request for simple casts like this, or is this feature missing by design?

It isn’t a simple cast which is the problem. It might be simple to go between String and Number but what about DateTime, Color, etc?

I don’t know if there is an issue open but I do know it’s not something simple to implement.

Rik very kindly helped me with a similar issue, when I wanted to perform a calculation with the result of a Exec Binding.

My use case was a One-Wire water tank thermostat.

The rule looks Iike this :-

var int offset = 10
var int target = 25
var int High = 26
var int Low = 23
var int temp = 30
var Timer Timer1 = null



rule "reset thermostat"
when
    System started
then
	target = 20
	offset = 10
	temp = 21
	OneWire_Thermostat_Tolerance.sendCommand(30)
	OneWire_Thermostat_SetPoint.sendCommand(20)
	OneWire_Temperature_Output.sendCommand(20)
	say("Hello. This is the One Wire thermostat rule", "voicerss:enGB", "webaudio")
	OneWire_Thermostat_Switch.sendCommand(OFF)
	
end


rule "One-Wire Thermostat"

when
     Item OneWire_Temperature_LastExecution changed or Item OneWire_Thermostat_Tolerance changed or Item OneWire_Thermostat_SetPoint changed
then


	target = (OneWire_Thermostat_SetPoint.state as Number)

// Rik's clever bit
	temp = Float::parseFloat(String::format("%s",OneWire_Temperature_Output.state))
	
	
	High = (target as DecimalType) + (offset  as DecimalType)
	Low = (target as DecimalType) - (offset  as DecimalType)
	//  say("Offset at " + offset + "Target at " + target + "Temperature at " + temp +"High at " + High + "Low at " + Low, "voicerss:enGB", "webaudio")


 			if ( (temp as Number) < (Low as Number) ){
			OneWire_Thermostat_Switch.sendCommand(ON)
			
			say("Temp is"+ temp + "Target is " + target + " " + "Heat is " +OneWire_Thermostat_Switch.state, "voicerss:enGB", "webaudio")
 			}
			
			else if( (temp as Number) > (High as Number)){
			OneWire_Thermostat_Switch.sendCommand(OFF)
			
			say("Temp is"+ temp + "Target is" + target + " " + "Heat is " +OneWire_Thermostat_Switch.state, "voicerss:enGB", "webaudio")
 			
 			}

end

I hope the clever code in the middle helps you.

More information on this is available here -

1 Like