Smarthome: UoM: 'toUnit' is not a member of 'org.eclipse.smarthome.core.library.types.QuantityType'

Created on 17 Jun 2018  路  2Comments  路  Source: eclipse-archived/smarthome

In a rule under OH 2.3.0, I receive this log error:

'toUnit' is not a member of 'org.eclipse.smarthome.core.library.types.QuantityType'

in reaction to the expression MyItemName.state.toUnit('mph') for a Number:Speed item. Also, an attempt to import tec.uom.se.AbstractUnit at the top of the rule does not result in resolving AbstractUnit when the rule tries to use the parse static method.

@kaikreuzer:

I have seen the same error and wondered why it happened. We might need some implicit imports in Xbase for it - @watou I would say that this is worth a separate issue (as I consider it a bug).

See https://github.com/eclipse/smarthome/issues/5243#issuecomment-397846492

Example rule that produces the log message:

import java.net.URLEncoder
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Map
import java.util.TimeZone
import tec.uom.se.AbstractUnit

/* Uploads weather station data using this format:

   http://wiki.wunderground.com/index.php/PWS_-_Upload_Protocol
 */

rule PWS
when
    Item DavisVantageVueWindDirectionAverage received update
then
    val sdf = new SimpleDateFormat('yyyy-MM-dd HH:mm:ss')
    sdf.setTimeZone(TimeZone.getTimeZone('UTC'))
    val Map<String, Object> params = newLinkedHashMap(
        'action' ->           'updateraw',
        'ID' ->               'XXXX',
        'PASSWORD' ->         'xxxx',
        'dateutc' ->          sdf.format(new Date()),
        'winddir' ->          DavisVantageVueWindDirection.state,
        'windspeedmph' ->     DavisVantageVueWindSpeed.state.toUnit('mph'),
        'windgustmph' ->      DavisVantageVueWindSpeedMaximum.state.toUnit('mph'),
        'windgustdir' ->      DavisVantageVueWindDirectionAverage.state,
        'windspdmph_avg2m' -> DavisVantageVueWindSpeedAverage.state.toUnit('mph'),
        'winddir_avg2m' ->    DavisVantageVueWindDirectionAverage.state,
        'humidity' ->         DavisVantageVueHumidity.state,
        'tempf' ->            DavisVantageVueOutdoorTemperature.state.toUnit('掳F'),
        'rainin' ->           DavisVantageVueRainCurrentHour.state.toUnit('in'),
        'baromin' ->          MeteoStickPressure.state.toUnit('inHg'),
        'softwaretype' ->     'openHAB 2.3')

    var url = 'https://weatherstation.wunderground.com/weatherstation/updateweatherstation.php?'
    var first = true
    for (key : params.keySet()) {
        if (!first) {
            url += '&'
        }
        url += key + '=' + URLEncoder::encode(params.get(key).toString, 'UTF-8')
        first = false
    }

    logDebug('PWS', 'url is {}', url)
    sendHttpGetRequest(url)
end
DSLRules bug

Most helpful comment

I did some analysis, it seems we have multiple problems:

  1. Your rule is actually not correct. DavisVantageVueWindDirection.state provides you a State and toUnit is indeed not defined on State. If you instead do a DavisVantageVueWindDirection.getStateAs(QuantityType).toUnit('mph'), all should work as expected.
  2. I would have expected a warning in the log at loading time of the rule, when such a problem exists. I have checked VS Code with LSP support enabled and this shows that the runtime is actually capable of finding this through static analysis:
    screen shot 2018-06-18 at 15 25 57 I do not know, why it fails to log this message upon loading of the file as well.
  3. The message that is logged during runtime is confusing. What it probably tries to say is 'toUnit' is not a member of State, but it prints the type of the actual instance, which is by chance a QuantityType, in which case (only) the statement is actually incorrect. It should either correctly state that it is not defined on State or it should succeed in finding the method and execute it.

All 2 comments

I did some analysis, it seems we have multiple problems:

  1. Your rule is actually not correct. DavisVantageVueWindDirection.state provides you a State and toUnit is indeed not defined on State. If you instead do a DavisVantageVueWindDirection.getStateAs(QuantityType).toUnit('mph'), all should work as expected.
  2. I would have expected a warning in the log at loading time of the rule, when such a problem exists. I have checked VS Code with LSP support enabled and this shows that the runtime is actually capable of finding this through static analysis:
    screen shot 2018-06-18 at 15 25 57 I do not know, why it fails to log this message upon loading of the file as well.
  3. The message that is logged during runtime is confusing. What it probably tries to say is 'toUnit' is not a member of State, but it prints the type of the actual instance, which is by chance a QuantityType, in which case (only) the statement is actually incorrect. It should either correctly state that it is not defined on State or it should succeed in finding the method and execute it.

With your explanation, the rule below now works! All of the unit conversions look correct. Of course, your points 2 and 3 would be best addressed.

import java.net.URLEncoder
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Map
import java.util.TimeZone

/* Uploads weather station data using this format:

   http://wiki.wunderground.com/index.php/PWS_-_Upload_Protocol
 */

rule PWS
when
    Item DavisVantageVueWindDirectionAverage received update
then
    val id = 'XXXX'
    val pw = 'xxxx'
    val sdf = new SimpleDateFormat('yyyy-MM-dd HH:mm:ss')
    sdf.setTimeZone(TimeZone.getTimeZone('UTC'))
    val Map<String, Object> params = newLinkedHashMap(
        'action' ->           'updateraw',
        'ID' ->               id,
        'PASSWORD' ->         pw,
        'dateutc' ->          sdf.format(new Date()),
        'winddir' ->          DavisVantageVueWindDirection.getStateAs(QuantityType).toUnit('掳').intValue,
        'windspeedmph' ->     DavisVantageVueWindSpeed.getStateAs(QuantityType).toUnit('mph').doubleValue,
        'windgustmph' ->      DavisVantageVueWindSpeedMaximum.getStateAs(QuantityType).toUnit('mph').doubleValue,
        'windgustdir' ->      DavisVantageVueWindDirectionAverage.getStateAs(QuantityType).toUnit('掳').intValue,
        'windspdmph_avg2m' -> DavisVantageVueWindSpeedAverage.getStateAs(QuantityType).toUnit('mph').doubleValue,
        'winddir_avg2m' ->    DavisVantageVueWindDirectionAverage.getStateAs(QuantityType).toUnit('掳').intValue,
        'humidity' ->         DavisVantageVueHumidity.state,
        'tempf' ->            DavisVantageVueOutdoorTemperature.getStateAs(QuantityType).toUnit('掳F').doubleValue,
        'rainin' ->           DavisVantageVueRainCurrentHour.getStateAs(QuantityType).toUnit('in').doubleValue,
        'baromin' ->          MeteoStickPressure.getStateAs(QuantityType).toUnit('inHg').doubleValue,
        'softwaretype' ->     'openHAB 2.3')

    var url = 'https://weatherstation.wunderground.com/weatherstation/updateweatherstation.php?'
    var first = true
    for (key : params.keySet()) {
        if (!first) {
            url += '&'
        }
        url += key + '=' + URLEncoder::encode(params.get(key).toString, 'UTF-8')
        first = false
    }

    logDebug('PWS', 'url is {}', url)
    sendHttpGetRequest(url)
end
Was this page helpful?
0 / 5 - 0 ratings