Mobile Alerts and openHAB 2

Haha someone actually following my API post… I set a trigger to detect :slight_smile:

For the first question. I will post later when I am home but its very similiar to the regex you used to get the numbers out of the http sensor web cache.

With the API call you will see in the log the result of the curl command as an update of the MobileAlertsAPI item. There will you can see the data returned from the sh script. This is the code used for the regex extraction. If you copy this you can test your regex expression in one of those free regex test sites. I used regex101. // needed for Openhab can cause an issue on some sites but changing it to / works for testing on regex101.

If your devices are different then you will needed to adapt the regex expression. I posted wind as an example since you were talking about that but I also use it for the rain gauge too. Its more accurate numbers than the sensor page cache as it returns the unrounded bucket tip volume 0.258ml per tip.

The API call should work for all the ‘pro’ rated sensors.

For the second question. Do you recognise the IP? Its not mobile alerts sensor page! Local IP ? This is for the sensor web caching method with http binding, right?

M

Hi Mark

great, thank you.
oooh I understand and had change to http://measurements.mobile-alerts.eu/Home/SensorsOverview?phoneid=XXXXXYYYYY
Sorry for this!
Now I had this error:

`[ERROR] [org.jupnp.transport.spi.StreamClient] - Request: HttpRequest[GET /HNAP1/ HTTP/1.1]@f73b68 failed

java.lang.NullPointerException: Missing SslContextFactory

at java.util.Objects.requireNonNull(Objects.java:228) ~[?:?]

at org.eclipse.jetty.io.ssl.SslClientConnectionFactory.<init>(SslClientConnectionFactory.java:50) ~[75:org.eclipse.jetty.io:9.4.11.v20180605]

at org.eclipse.jetty.client.HttpClient.newSslClientConnectionFactory(HttpClient.java:1155) ~[71:org.eclipse.jetty.client:9.4.11.v20180605]

at org.eclipse.jetty.client.HttpDestination.newSslClientConnectionFactory(HttpDestination.java:138) ~[71:org.eclipse.jetty.client:9.4.11.v20180605]

at org.eclipse.jetty.client.HttpDestination.<init>(HttpDestination.java:95) ~[71:org.eclipse.jetty.client:9.4.11.v20180605]

at org.eclipse.jetty.client.PoolingHttpDestination.<init>(PoolingHttpDestination.java:25) ~[71:org.eclipse.jetty.client:9.4.11.v20180605]

at org.eclipse.jetty.client.http.HttpDestinationOverHTTP.<init>(HttpDestinationOverHTTP.java:32) ~[71:org.eclipse.jetty.client:9.4.11.v20180605]

at org.eclipse.jetty.client.http.HttpClientTransportOverHTTP.newHttpDestination(HttpClientTransportOverHTTP.java:51) ~[71:org.eclipse.jetty.client:9.4.11.v20180605]

at org.eclipse.jetty.client.HttpClient.destinationFor(HttpClient.java:539) ~[71:org.eclipse.jetty.client:9.4.11.v20180605]

at org.eclipse.jetty.client.HttpClient.send(HttpClient.java:572) ~[71:org.eclipse.jetty.client:9.4.11.v20180605]

at org.eclipse.jetty.client.HttpRequest.send(HttpRequest.java:727) ~[71:org.eclipse.jetty.client:9.4.11.v20180605]

at org.eclipse.jetty.client.HttpRequest.send(HttpRequest.java:680) ~[71:org.eclipse.jetty.client:9.4.11.v20180605]

at org.jupnp.transport.impl.jetty.JettyStreamClientImpl$1.call(JettyStreamClientImpl.java:155) [212:org.jupnp:2.5.1]

at org.jupnp.transport.impl.jetty.JettyStreamClientImpl$1.call(JettyStreamClientImpl.java:1) [212:org.jupnp:2.5.1]

at org.jupnp.transport.spi.AbstractStreamClient$RequestWrapper.call(AbstractStreamClient.java:204) [212:org.jupnp:2.5.1]

at org.jupnp.transport.spi.AbstractStreamClient$RequestWrapper.call(AbstractStreamClient.java:1) [212:org.jupnp:2.5.1]

at java.util.concurrent.FutureTask.run(FutureTask.java:266) [?:?]

at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [?:?]

at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [?:?]

at java.lang.Thread.run(Thread.java:748) [?:?]`

regards
Marco

You can simply use the sensor web page url in your favourite browser to view it like any other web page. Then if you extract the source code this is the code the js transform regex is operating on and you can test it all works in an online tester. Its kind of fun to play around with the regex and see the online tester response

JS transforms for API call

API wind direction as a number 0-16

(function(i) {
    var re = new RegExp('"wd":[\\s\\S]*?([0-9]+)');
    var out = i.match(re)[1];
    return parseFloat(out);
})(input)

API wind gust

(function(i) {
    var re = new RegExp('"wg": "([0-9]+.[0-9]+|[0-9]+)",');
    var out = i.match(re)[1];
    return parseFloat(out);
})(input)

API wind speed

(function(i) {
    var re = new RegExp('"ws": "([0-9]+.[0-9]+|[0-9]+)",');
    var out = i.match(re)[1];
    return parseFloat(out);
})(input)

Here is a JS transform for API wind direction as compass bearing. I am not using this at the moment and I can’t remember if I tested it!! return parseFloat(out) doesn’t seem right for a string but maybe it worked and I left like that? Alternatively you could use a map transform on the number and then have both numbers and compass bearing to use. Also, Grafana does value mapping too.

function(i) {
    var re = new RegExp('"wd":[\\s\\S]*?([0-9]+)');
    var direction = i.match(re)[1];
    var out = ''
    if (direction = 1.0) {
        out = 'NNE'}
    if (direction = 2.0) {
        out = 'NE'}
    if (direction = 3.0) {
        out = 'NNE'}
    if (direction = '4.0') {
        out = 'NNE'}
    if (direction = '5.0') {
        out = 'NNE'}
    if (direction = '6.0') {
        out = 'NNE'}
    if (direction = '7.0') {
        out = 'NNE'}
    if (direction = '8.0') {
        out='NNE'}
    if (direction = '9.0') {
        out = 'NNE'}
    if (direction = '10.0') {
        out = 'NNE'}
    if (direction = '11.0') {
        out = 'NNE'}
    if (direction = '12.0') {
        out = 'NNE'}
    if (direction = '13.0') {
        out='NNE'}
    if (direction = '14.0') {
        out = 'NNE'}
    if (direction = '15.0') {
        out = 'NNE'}
    if (direction = '16.0') {
        out = 'NNE'}
    return parseFloat(out);
})(input)

API rain

(function(i) {
    var re = new RegExp('"r":[\\s\\S]*?([0-9]+.[0-9]+)');
    var out = i.match(re)[1];
    return parseFloat(out);
})(input)

As motivation here is what you end up with when its all working. 2 day plot in Grafana of the API rain result

UPDATE: It suddenly works!!!

No success for me with the following device.
http binding and RegEx installed.
I cannot see any log entries… no output, nothing… as if nothing is happening.
Do I need to start up something?

http://measurements.mobile-alerts.eu/Home/SensorsOverview?phoneid=phone_id
is working in the browser.

What is wrong?

<div class="sensor-header">
    <h3>
        <a href="/Home/MeasurementDetails?deviceid=sensor_id&amp;vendorid=8B9F7B80-20FE-42F6-ACE9-F74E6EF862B9&amp;appbundle=de.synertronixx.remotemonitor">Wetterstation 1.OG</a>
    </h3>
    <div class="sensor-component">
        <h5>ID</h5>
        <h4>sensor_id</h4>
    </div>
</div>

<div class="nofloat"></div>

    <div class="sensor-component">
        <h5>Zeitpunkt</h5>
        <h4>07.07.2019 16:14:33</h4>
    </div>
    <div class="sensor-component">
        <h5>Temperatur Innen</h5>
        <h4>25,4 C</h4>
    </div>
    <div class="sensor-component">
        <h5>Luftfeuchte Innen</h5>
        <h4>66%</h4>
    </div>
    <div class="sensor-component">
        <h5>Temperatur Au&#223;en</h5>
        <h4>23,7 C</h4>
    </div>
    <div class="sensor-component">
        <h5>Luftfeuchte Au&#223;en</h5>
        <h4>55%</h4>
    </div>
        </div>
    </div>
</div>

http.cfg located in conf/services

sensorCache.url=http://measurements.mobile-alerts.eu/Home/SensorsOverview?phoneid=sensor_id
sensorCache.updateInterval=60000

items:

Number inTemperature "Temperatur innen [%.1f °C]" { http="<[sensorCache:60000:JS(getIDTemperature.js)]" }
Number inHumidity "Feuchtigkeit innen [%d %%]" { http="<[sensorCache:60000:JS(getIDHumidity.js)]" }

sitemap:

        Text label="Wetterstation (Mobile Alerts)" icon="sun_clouds" {
            Text item=inTemperature icon="temperature"
            Text item=inHumidity icon="humidity"

*.js located in conf/transform
I tried 2 versions each…

getIDTemperature.js

(function(i) { 
    var re = new RegExp('sensor_id[\\s\\S]*?Temperatur Innen[\\s\\S]*?<h4>([0-9]+.[0-9]+) C');
    var out = i.match(re)[1]; 
    return parseFloat(out.replace(',', '.')); 
})(input)
(function(i) {
    var re = new RegExp('Temperatur Innen<\/h5>\\s*<h4>([0-9]+,[0-9]+) C<\/h4>', 'm');
    var out = i.match(re)[1];
    return parseFloat(out.replace(',', '.'));
})(input)

getIDHumidity.js

(function(i) { 
    var re = new RegExp('sensor_id[\\s\\S]*?Luftfeuchte Innen[\\s\\S]*?<h4>([0-9]+)%');
    var out = i.match(re)[1]; 
    return parseFloat(out);
})(input)
(function(i) {
    var re = new RegExp('Luftfeuchte Innen<\/h5>\\s*<h4>([0-9]+)%<\/h4>', 'm');
    var out = i.match(re)[1];
    return parseFloat(out);
})(input)

Any idea?

What did you do to fix it?

Nothing… as I wrote, it suddenly worked after struggeling for hours.
I haven’t made any changes to the configs I posted.

Added improvement in the RegEx expression to prevent incorrect values when a device isn’t reporting

eg temperature … I added in the capture group an Or for —

var re = new RegExp('<device id>[\\s\\S]*?Temp 1[\\s\\S]*?<h4>([0-9]+.[0-9]+|-[0-9]+.[0-9]+|---)');

I don’t do anything when this happens. The temperature item just isn’t updated and I see that in the charts.

Hey Marco,
do you a way, not just to show rain last 24h, rather every 30 or 60 min and for 24 h?
At “https://measurements.mobile-alerts.eu/Home/MeasurementDetails” there is a value every 5 min.

Greetings, Ansgar

Why not use the API? … like this… I have posted this before in this thread

Item to hold the returned data from API request

String MobileAlertsAPI "Mobile-Alerts API query" <text> { channel="exec:command:mobilealertsAPI:output" } // run every 5mins. See Thing

EXEC binding Thing to run an a script to make the API request for the data

Thing exec:command:mobilealertsAPI "MobileAlerts API" [command="/home/openhabian/Mobile-Alerts_REST_API.sh", interval=300, timeout=15]

API script that is run by EXEC Thing every 5mins

curl -d deviceids=xxxx,yyyy -d phoneid=zzzzz https://www.data199.com/api/pv1/device/lastmeasurement

Rule to run a transform on the results. Similar to the regex for the html cache.

rule "Mobile-Alerts API"
when
    Item MobileAlertsAPI changed
then

etc etc

API method is better than HTML cache for some sensors and works for wind too. I posted somewhere in this thread further details on the rule.

Then use Influx and Grafana to create charts with 5min resolution for any time period you want
eg 7 day


zoomed in

My items are failing to update at the moment and the openHAB log fills up with this

2020-02-12 11:12:35.751 [ERROR] [org.openhab.io.net.http.HttpUtil    ] - Fatal transport error: java.net.SocketTimeoutException: Read timed out

2020-02-12 11:12:35.753 [ERROR] [ab.binding.http.internal.HttpBinding] - No response received from 'sensorCache'

The mobile-alerts measurements web page responds with this

or

image

https://measurements.mobile-alerts.eu/Home/SensorsOverview?phoneid=phoneidhere

REST API is still working

Has anyone else noticed the same?

Hey Mark,
same probleme here since tuesday morning.

I wanna try it with the REST API in the next days.

Hi. I contacted mobile-alerts and they replied. They are aware of the problem and have alerted their service provider.

I think this is the second time I have seen issues with the sensor web page. This time the fix seems slower to come. Too slow. They just said use your phone app to view your data. Hmmmm.

So, like you I am moving more of the openhab sensor data collection over from webpage caching method to REST API. I have a mix of both methods.

However, API isn’t available for all sensor types. I should complete today a check of the list of supported sensor types that’s in the mobile-alerts API info doc. So, far it seems up to date. I will post later which devices and which cannot use the API method.

Which brings me to an interesting point. Despite the web server fail the app continues to work for all device types.

So, it would be good to know how the app is getting the data for device types which are not supported for API. I don’t have the skills to sniff around and so I hope someone here has and the motivation, or maybe one the contributors to the mobile-alerts github documentation. :grinning:

I would be very glad about such a list.

Unfortunately I do not know how the app is getting the data, but yes my app still works too.

mobile-alerts API documentation

Device type is indicated by first two characters of the device ID

Listed API supported devices.
WInd, Rain and Pro devices

01 Temperature with probe . not tested
08 Rain gauge. OK
09 Temperature/Humidity with probe. OK
0B Wind anemometer. OK
0E Temperature/Humidity … not tested

Tested and found to be unsupported:
02 Temperature
03 Temperature/Humidty
11 Temperature/Humidty station
12 Humidity station

So, as far as I can tell the above linked doc appears complete

Update…sensor web page is working on and off

https://measurements.mobile-alerts.eu/

but I am still going to move my pro sensors to API.

If you are using the API method and update your openhab to 2.5.2 then beware the following:

edit…
I improved the API rule to better capture when the REGEX fails and to track how long has elapsed since a sensor was ‘last seen’. I will post the rule code if anyone is interetsed.

I found for the rain sensor the rainfall ammount value dissapears in the API return result after some time but returnsagain if there is any rain. It could also be related to the recent poor performance of the sensor web server. This disappeared value causes the REGEX to fail and when it fails it retruns the full API string (not null as I had previously and erroneously assumed)

Hey Mark,
is it possible to use the same way to get the battery level?

Yes, e.g.

"lowbattery": false

The http measurement web page has been performing badly for sometime now. The web server seems to have stopped for http requests. I see 403 error. The app seems unaffected and the REST API is still working but that doesn’t work for non pro sensors.

Is anyone else having trouble with the http cache method?