[SOLVED] Setting a Location directly

All,

I am trying to set a Location item directly:

Location_Home.postUpdate(new PointType(xx.580689,x.955827))

But I get:

 Error during the execution of rule 'Set Home and Garage Position': An error occurred during the script execution: Cannot convert number literal to typeorg.eclipse.smarthome.core.library.types.DecimalType

If I do it this way, it’s working properly, but I would like to reduce the code as good as possible:

Location_Home_Lat.postUpdate(xx.580689)
Location_Home_Lon.postUpdate(x.955827)
Location_Home.postUpdate(new PointType(Location_Home_Lat.state as DecimalType, Location_Home_Lon.state as DecimalType))

From the docs:

PointType

PointType strings consist of three DecimalType s separated by commas, indicating latitude and longitude in degrees, and altitude in meters respectively.

Therefore your command will be:

Location_Home.postUpdate(new PointType(xx.580689,x.955827, 0.0))

Or whatever altitude (in meters)

Altitude is optional.

The docs are a bit ambiguous, note the mention of ‘string’.
This is valid -

   // one string
var PointType myLoc = new PointType("52, 4.5")
   // created string
var PointType hisLoc=new PointType(hisLat.state.toString + " , " + hisLong.state.toSring)

I’m surprised the OP example with two DecimalType works.

So even though it’s DecimalType, the Location just accepts one string?
That’s weird.
But if this works, I am fine with it :wink:

EDIT:
it does work!
Thank a lot

I’ve not been involved with these things, just remembered an older thread with similar troubles.

PointType ( Number, Number) would seem like the logical construction. Parsing of strings / string to numbers, which might include various separators or compass points, decimals or minutes, etc. would be left up to the user.
Flexible.

PointType ( String ) would be convenient sometimes, but only when your string is in the expected format. Useless if you are doing any calculations e.g. plotting a path.

I suppose this is ESH stuff. This debate has been had before of course -
https://bugs.eclipse.org/bugs/show_bug.cgi?id=467612

There it suggests that
PointType ( DecimalType, DecimalType )
PointType ( String ) - where string is in a set format
should both work.
Within OpenHAB you may have to take care to get e.g. Number into Decimal form.

@rossko57

Hi rossko57

Small question to you. I try to measure distance of my Tesla to a fixed location with following rule:

rule "Tesla"
when
    Item TeslaLocation received update
then
    val PointType home = new PointType(xx.459301,xx.429143)
    val x = (home as LocationItem).distanceFrom(TeslaLocation as LocationItem)
    HomeDist.postUpdate(x)
end

However this does not work I messed somehow the valuetypes PointType and LocationItem. I’m not used to deal with location type of items. Do you have an idea what is wrong here?

Thank you very much in advance for your help

For a start, you could look in your openhab.log for an error.
I’ve never seen ‘as LocationItem’ used before. How does that work? Do Items have a distanceFrom method?

The more usual way would be using PointType variables like here

I use the disctance calulation in a rule triggered by a Group
(see also Design Pattern: Working with Groups in Rules)

This means I just have one rule for all distances (myself, my wife, our son, our car).
I stripped it down a little and I hope it helps (and I did not delete too much.
Essentially all triggering items in the G_Loc group are Location items and look like Myself_Loc or Car_Loc:

//********************** GEOFENCING rules **********************
import org.openhab.core.model.script.ScriptServiceUtil

/////////////  Distance Stuff //////////////////////////////////////////////////////////////////////////////
rule "Geo Distance calculation"
when
    Member of G_Loc changed
then
	val itemName = triggeringItem.name.toString
	val location = triggeringItem.state.toString // triggering location item state
// cancel if NULL
	if(location == NULL) return; // failing fast
	logInfo("+++ GEOFENCING", "Distance: Member of G_Loc changed: " + itemName)
// who changed (triggered) to which location?
	val String who = itemName.replaceAll("_Loc", "") // all my location items are of type "Person_Loc" or "Car_Loc"
	val PointType loc = triggeringItem.state as PointType // for .distanceFrom either both need to be PointType or Location - I guess and don't know, what's the difference between them.
// stop here if home Location is not set yet
	if(Loc_Home.state == NULL) {
		logInfo("+++ GEOFENCING", "Loc_Home not initialized - distance calculation skipped.")
		return;
	}
// stuff for home distance calculation / check for who's distance from home
	val PointType home = Loc_Home.state as PointType
	val String whoDH = who + "_Dist" // distance (item name) from home for who
	val whoDHitem = ScriptServiceUtil.getItemRegistry.getItem(whoDH) // distance (real item itself) from home for who
	val distH = (loc.distanceFrom(home))
	postUpdate(whoDHitem, distH)
	logInfo("+++ GEOFENCING", "G_Location of " + itemName + " changed to HOME Distance of " + distH.format("%.0f"))
end

I hope it helps.

That is the log entry I get:


2021-03-05 18:00:43.926 [INFO ] [el.core.internal.ModelRepositoryImpl] - Validation issues found in configuration model 'Tesla.rules', using it anyway:
Cannot cast from PointType to LocationItem

@NCO: that was the idea I followed to calculate distance

I thought it could be quite simple.

@rlkoshak Sorry to bother you too. Could you give me a hint how I can deal with the two value types. See [SOLVED] Setting a Location directly - #6 by Logos

Thank you all for the support

You should go back and review the concepts sections of the docs again. Items carry a state. They are not the state itself. The LocationItem carries a PointType as the state. A LocationItem is not a PointType. You can’t cast a PointType to a LocationItem. They are two completely different things.

So in this case you have a PointType.

TeslaLocation is a LocationItem that itself has a state that is a PointType.

PointType has a distanceFrom() method that takes another PointType as an argument.

LocationItem has a distanceFrom() method that takes another LocationItem as an argument.

You can’t magically turn a PointType into a LocationItem. But a LocationItem carries a PointType as it’s state.

val x = home.distanceFrom(TeslaLocation.state as PointType)

Finally, it’s always better to start a new thread rather than reopening a two year old thread.

1 Like

I don’t remember exactly what’s the difference between PointType and Location, but check out @rlkoshak explenation above.
This works for me:

  1. assuming you have your home location defined as a Location item: e.g. Home_Loc
  2. TeslaLocation is also a Location Type item

Make a Point type out of your TeslaLocation and your Home_Loc:

val PointType tesla = TeslaLocation.state as PointType
val PointType home = Home_Loc.state as PointType
val distH = (tesla.distanceFrom(home))

Hi Rich

Thank you very much for your comments. As always very much to the point and enlightening. I understand the difference between state and items but have to admit that I never used location items so far and did not realize how to correctly use it… so new learning and sorry for that.

So I implemented based on your comment:

rule "Tesla"
when
	Item TeslaLocation received update
then
    val PointType home = new PointType(xx.459301, xx.429143)
	val x = home.distanceFrom(TeslaLocation.state as PointType)
	HomeDist.postUpdate(x)
end

But still get this error:

10:54:20.662 [ERROR] [.internal.handler.ScriptActionHandler] - Script execution of rule with UID 'Tesla-1' failed: An error occurred during the script execution: Could not invoke constructor: org.openhab.core.library.types.PointType.PointType(org.openhab.core.library.types.StringType,org.openhab.core.library.types.StringType) in Tesla

Apparently there is something wrong with the val definition:

val PointType home = new PointType(xx.459301, xx.429143)

Do you have an idea how to correctly set the value?

@NCO thank you too for your comments, exactly along the lines of Rich.

It’s probably one of those silly quirks where the’re the "wrong kind"of numbers.
You could try the alternate method of parsing from one string.

val PointType home = new PointType("xx.459301, xx.429143")

Hi rossk57

Thank you very much, this did the trick.

Also thanks to @rlkoshak and @NCO for supporting me in this issue

No worries - that’s why we’re all here, I suppose :slight_smile:

Actually, I am happier than you if I am able to give something back, now that I have received so much support in this community.

I would not be where I am with OH without this awesome community and all its contributors and maintainers!

Location is the Item type. PointType is the State.

So Location is to Switch as PointType is to OnOffType.

Looking at the JavaDocs (linked to above, really everyone should book mark the JavaDocs, there is a wealth of information in there) PointType has constructors that accept:

  • String: presumably lat,long type formatted string “12.123454,34.12345”
  • DecimalType lat, DecimalType long
  • DecimalType lat, DecimalType long, DecimalType alt
  • StringType lat, StringType long
  • StringType lat, StringType long, StringType alt

Notice, Number, BigDecimal, and float are not among the supported types. You either need to provide your coordinates as a String, or create a DecimalType or a StringType to pass as the arguments. Note, anything you see that ends in “Type” is going to be an Item’s state type of object.

I need to add a section to my openhab 3 tips and tricks talking about the JavaDocs. I can’t tell you how many times I’ve used it to answer questions on this forum just this week.

2 Likes

Separate strings as well - that’s good to know.

I can imagine, because whenever I come up with an issue, you are there :slight_smile:
So as stated above I am extremely appreciative for your contribution.