Dear Openhab Mates,
I think is interesting to share my experience for other that want to reply the case.
1 - Decide the triggering item that you want to actrivate the rule that push the image as broadcast notification (I’m at the moment implementing a way to intercept standard doorbell ringing as trigger, but that is another story)
1 - Implement as Thing an IP camera or any device running with IpCameraBinding
2 - Create an Image item in your Model (“TestImage” for example)
3 - copy paste these Rule:
import java.net.URL
import java.util.Base64
rule "Send doorbell push with pics"
when
Item TRIGGERING_ITEM changed from OFF to ON
then
executeCommandLine("wget", "http://OPENHABIANIP:8080/ipcamera/IPCAMERAUID/ipcamera.jpg", "-O", "/etc/openhab/html/CAMIMAGE.jpg");
val imageUrl = "http://OPENHABIANIP:8080/static/CAMIMAGE.jpg"
val username = "YOURopenhabianUSER"
val password = "YOURopenhabianPASS"
val url = new URL(imageUrl)
val connection = url.openConnection()
val userpass = username + ":" + password
val basicAuth = "Basic " + new String(Base64.getEncoder().encode(userpass.getBytes()))
connection.setRequestProperty("Authorization", basicAuth)
val contentType = connection.getContentType()
val bytes = connection.getInputStream().readAllBytes()
val image = new RawType(bytes, contentType)
TestImage.postUpdate(image)
sendBroadcastNotification("Test", "motion", "Tag",
"Title, "id-1234", null, "item:TestImage",
null, null, null)
end
in that way, TestImage will be sended also if you are not in the same network of your openhabian system!
Thanks for posting! This is a great candidate for a rule template. That way users can just install and configure the rule instead of needing to copy/paste/edit.
If you are willing I’m willing to help. You can keep it as Rules DSL but it will need to be reformatted as a managed rule. But as a rule tempalte, the TRIGGERINT_ITEM, imageURL, username, and password would all be configuration properties.
I tried to do the whole thing in Javascript because I don’t want to use DSL, but I get the following error message. I can’t find anything in the forum that helps me. Does anyone have any ideas?
Error
2025-01-14 11:40:52.789 [WARN ] [rnal.defaultscope.ScriptBusEventImpl] - State 'raw type (image/jpeg): 356597 bytes' cannot be parsed for item 'TestImage'.
Code
urlType = Java.type("java.net.URL");
base64Type = Java.type("java.util.Base64");
RawType = Java.type("org.openhab.core.library.types.RawType");
actions.Exec.executeCommandLine("wget", "http://192.168.53.68:8080/ipcamera/DoorbellReolink/image.jpg", "-O", "/etc/openhab/html/CAMIMAGE.jpg");
var imageUrl = "http://192.168.53.68:8080/static/CAMIMAGE.jpg";
var username = "YOURopenhabianUSER";
var password = "YOURopenhabianPASS";
var url = new urlType(imageUrl);
var connection = url.openConnection();
var userpass = username + ":" + password;
var basicAuth = "Basic " + new String(base64Type.getEncoder().encode(userpass.getBytes()));
connection.setRequestProperty("Authorization", basicAuth);
var contentType = connection.getContentType();
console.log("copyImageLocal: " + "after contentType [ " + contentType.toString() + " ]");
var bytes = connection.getInputStream().readAllBytes();
console.log("copyImageLocal: after bytes");
var image = new RawType(bytes, contentType);
console.log("copyImageLocal: after rawType");
items.getItem("TestImage").postUpdate(image);
This might be a case where JS’s wrapping of everything causes problems.
In Rules DSL additional postUpdate methods are patched onto the Item Object that take in additional compatible Item types (e.g. in this case a raw binary jpg). But in all the other languages those additional methods are not available. No matter what you pass to postUpdate, it’s going to be converted to a String because in the non-Rules DSL languages all that we have is the postUpdate(String, String) Action.
IIRC the Image Item does support Base64 encoded images and you are already importing the Base64 utility. But I don’t know if just running the binary through an encode is good enough.
var URL = Java.type("java.net.URL");
const url = new URL(camurl);
const connection = url.openConnection();
const contentType = connection.getContentType();
const inputStream = connection.getInputStream();
const bytes = inputStream.readAllBytes();
const byteToBase64 = (byte) => {
const key = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
let bytes = new Uint8Array(byte)
let newBase64 = ''
let currentChar = 0
for (let i=0; i<bytes.length; i++) { // Go over three 8-bit bytes to encode four base64 6-bit chars
if (i%3===0) { // First Byte
currentChar = (bytes[i] >> 2) // First 6-bits for first base64 char
newBase64 += key[currentChar] // Add the first base64 char to the string
currentChar = (bytes[i] << 4) & 63 // Erase first 6-bits, add first 2 bits for second base64 char
}
if (i%3===1) { // Second Byte
currentChar += (bytes[i] >> 4) // Concat first 4-bits from second byte for second base64 char
newBase64 += key[currentChar] // Add the second base64 char to the string
currentChar = (bytes[i] << 2) & 63 // Add two zeros, add 4-bits from second half of second byte
}
if (i%3===2) { // Third Byte
currentChar += (bytes[i] >> 6) // Concat first 2-bits of third byte for the third base64 char
newBase64 += key[currentChar] // Add the third base64 char to the string
currentChar = bytes[i] & 63 // Add last 6-bits from third byte for the fourth base64 char
newBase64 += key[currentChar] // Add the fourth base64 char to the string
}
}
if (bytes.length%3===1) { // Pad for two missing bytes
newBase64 += `${key[currentChar]}==`
}
if (bytes.length%3===2) { // Pad one missing byte
newBase64 += `${key[currentChar]}=`
}
return newBase64
}
const image = "data:"+contentType+";base64," + byteToBase64(bytes);
itemImage.postUpdate(image);
If you write that rule in JRuby this is how it would look like:
IMAGE_SOURCE = "http://OPENHABIANIP:8080/ipcamera/IPCAMERAUID/ipcamera.jpg"
rule "Send doorbell push with pics" do
changed TRIGGERING_ITEM, from: OFF, to: ON
run do
TestImage.update_from_url IMAGE_SOURCE
Notification.send "Test",
icon: "motion",
tag: "Tag",
title: "Title",
id: "id-1234",
attachment: TestImage
end
end
Or with a UI rule, just drop those two instructions + the IMAGE_SOURCE from within the “run do … end” block into your script editor.