I installed a HomematicIP Weather station in my backyard last fall. I am very happy with it. I was eager to share my weather station on Weather Underground, but I discovered that the HomematicIP weather station is not compatible. As a workaround I created a rule that takes the data from the weather station, and sends it to WU using HTTPGET requests. Here is the rule:
// Rule Configuration
const STATION_ID = 'mystationid';
const STATION_KEY = 'mystationkey';
// 1. Fetch data from your Items
const tempC = items.getItem('HmIPWeatherStation_Actual_Temperature').numericState;
const humidity = items.getItem('HmIPWeatherStation_Humidity').numericState;
const windKmh = items.getItem('HmIPWeatherStation_Wind_Speed').numericState;
const lux = items.getItem('HmIPWeatherStation_Illumination').numericState;
const rainTotal = items.getItem('HmIPWeatherStation_Rain_Counter'); // Use the cumulative counter
// 2. Calculate Rain Deltas using Persistence
// WU wants "Rain since midnight" and "Rain in last hour"
const now = time.ZonedDateTime.now();
const startOfDay = now.withHour(0).withMinute(0).withSecond(0);
const oneHourAgo = now.minusHours(1);
// Get the difference in mm
const dailyRainMm = rainTotal.numericState - rainTotal.persistence.persistedState(startOfDay).numericState;
const hourlyRainMm = rainTotal.numericState - rainTotal.persistence.persistedState(oneHourAgo).numericState;
// 3. Perform Conversions (Metric to Imperial)
const tempF = (tempC * 1.8) + 32;
const windMph = windKmh * 0.621371;
const dailyRainIn = Math.max(0, dailyRainMm * 0.03937); // Ensure no negative values
const hourlyRainIn = Math.max(0, hourlyRainMm * 0.03937);
const solarRadiation = lux * 0.0079;
// 4. Construct the API URL manually
const baseUrl = "https://rtupdate.wunderground.com/weatherstation/updateweatherstation.php";
// We build the query string directly to avoid ReferenceErrors
let queryString = "?ID=" + STATION_ID;
queryString += "&PASSWORD=" + STATION_KEY;
queryString += "&dateutc=now";
queryString += "&tempf=" + tempF.toFixed(1);
queryString += "&humidity=" + humidity.toFixed(0);
queryString += "&windspeedmph=" + windMph.toFixed(1);
queryString += "&rainin=" + hourlyRainIn.toFixed(2);
queryString += "&dailyrainin=" + dailyRainIn.toFixed(2);
queryString += "&solarradiation=" + solarRadiation.toFixed(1);
queryString += "&softwaretype=openHAB_5.1_GraalJS";
queryString += "&action=updateraw";
const finalUrl = baseUrl + queryString;
// 5. Execution
try {
// Note: in openHAB GraalJS, 'actions.HTTP' is the standard way to call this
const response = actions.HTTP.sendHttpGetRequest(finalUrl, 5000);
if (response && response.includes("success")) {
return;
} else {
console.warn("WU: Upload Failed. Response from server: " + response);
}
} catch (e) {
console.error("WU: Communication Error: " + e);
}
Just a couple of things which could shorten some of these lines which makes them a little easier to read.
const tempC = items.HmIPWeatherStation_Actual_Temperature.numericState
const now = time.toZDT();
const startOfDay = time.toZDT('00:00'); // or
const startOfDay = time.toZDT('12:00 AM');
const dailyRainMm = rainTotal.persistence.deltaSince(startOfDay).numericState;
// This approach works for all the conversions
const tempF = items.HmIPWeatherStation_Actual_Temperature.quantityState.toUnit('°F').float;
If you keep the states as Quantity’s the whole rule can get shorter since you don’t actually use the SI units.
// Rule Configuration
const STATION_ID = 'mystationid';
const STATION_KEY = 'mystationkey';
// 1. Fetch data from your Items
const tempF = items.HmIPWeatherStation_Actual_Temperature.quantityState.toUnit('°F').float.toFixed(1);
const humidity = items.HmIPWeatherStation_Humidity.numericState.toFixed(0);
const windMph = items.HmIPWeatherStation_Wind_Speed.quantityState.toUnit('mph').float.toFixed(1);
const solarRadiation = items.HmIPWeatherStation_Illumination.quantityState.toUnit('W/m²'); //this one may not work
const rainTotal = items.HmIPWeatherStation_Rain_Counter; // Use the cumulative counter
// 2. Calculate Rain Deltas using Persistence
// WU wants "Rain since midnight" and "Rain in last hour"
const startOfDay = time.toZDT("00:00");;
const oneHourAgo = time.toZDT('PT-1H');
// Get the difference in inches
const dailyRainIn = rainTotal.persistence.deltaSince(startOfDay).quantityState.toUnit('in').float.toFixed(2);
const hourlyRainIn = rainTotal.persistence.deltaSince(oneHourAgo).quantityState.toUnit('in').float.toFixed(2);
// 3. Construct the API URL manually
const baseUrl = "https://rtupdate.wunderground.com/weatherstation/updateweatherstation.php";
// We build the query string directly to avoid ReferenceErrors
let queryString = "?ID=" + STATION_ID;
queryString += "&PASSWORD=" + STATION_KEY;
queryString += "&dateutc=now";
queryString += "&tempf=" + tempF;
queryString += "&humidity=" + humidity;
queryString += "&windspeedmph=" + windMph;
queryString += "&rainin=" + hourlyRainIn;
queryString += "&dailyrainin=" + dailyRainIn;
queryString += "&solarradiation=" + solarRadiation;
queryString += "&softwaretype=openHAB_5.1_GraalJS";
queryString += "&action=updateraw";
const finalUrl = baseUrl + queryString;
// 4. Execution
try {
// Note: in openHAB GraalJS, 'actions.HTTP' is the standard way to call this
const response = actions.HTTP.sendHttpGetRequest(finalUrl, 5000);
if (response && response.includes("success")) {
return;
} else {
console.warn("WU: Upload Failed. Response from server: " + response);
}
} catch (e) {
console.error("WU: Communication Error: " + e);
}
Rich, I have to admit, I sent my last reply while away from home and I was distracted. Although your suggestion of using quantityState was spot on, I had to use the item’s raw state to get it to work.
From what I could tell, items.<item>.state in openHAB returns a string representation of the state, not a typed QuantityTypeobject — so the .toUnit() method isn’t available on it, however rawState gives you the underlying Java QuantityType object directly, which has .toUnit() natively.
Would you be in agreement with that, or do I have an incorrect understanding of how this works?
I have discovered the root cause of the problems I was encountering with this rule and your code…it was me. I don’t know what I did to mess it up, but I did. Once I started fresh with this rule, using your code that you provided, and everything worked fine. My apologies, and thanks for your support and advise.