HI!
I think we could be talking into a mirror; I too have an industrial computer background and zero modern computer language skills
The setup is in a VM on a QNAP server, which is pretty similar to your Synology server. Are you looking to run OH3 within a VM on your Synology?
All the screens you’ve seen on my posts are automatically generated by OH3 based on the model of the house and the equipment in it – that’s been one of the best things about the move to OH3, it’s like the old OH2 basic UI just got transported in the 22nd century! I just added some real pictures, and borrowed some real pictures from google, for the room backgrounds; and voila!
I taught myself how to insert some YAML code - I basically copied the examples @ysc provided in one of the release notes and just changed the item names and now the location card then has temperature and humidity on it.
Likewise, the Equipment page is automatically generated from the model – so by placing each piece of equipment in a room, and declaring the type of equipment it is, OH3 generates the Equipment page, and likewise by categorising the important points of each piece of equipment the Properties page is again automatically generated. Of course I did need to download some more pretty background pictures
component: oh-property-card
config:
title: Temperatures
subtitle: "='Setpoint: ' + items.MT_AmbientSetpointPAD12.state"
backgroundImage: /static/files/temperature.jpg
slots:
glance:
- component: oh-link
config:
text: "='Supply: ' + items.MT_ActualHotWaterSupply.state"
iconF7: thermometer
iconColor: red
color: white
style:
font-size: 12px
margin-top: 8px
- component: oh-link
config:
text: "='Outside: ' + items.MT_OutsideTemperature.state"
iconF7: thermometer
iconColor: blue
color: white
style:
font-size: 12px
margin-top: 3px
component: oh-equipment-card
config:
backgroundImage: /static/files/battery.jpg
slots:
header:
- component: oh-gauge
config:
labelText: Powerwall
item: TeslaPowerwall_BatteryState
size: 250
value: 60
type: semicircle
borderColor: white
borderBgColor: rgba(255,255,255,0.4)
valueTextColor: white
labelTextColor: white
borderWidth: 20
style:
margin-left: 30px
It’s really great how the entire front end is generated from the model, and how little work is required if the model has been planned.
Where I’ve spent a bit more brain power is in developing (that makes me sound like a young techie!) what I like to call my Schrödinger’s cat roller blinds. Basically, all the blinds have RSI motors which are stateless so absolutely no way of knowing if they are UP (alive) or DOWN (dead); so, it’s a case of recording their last position and hoping that the dog hasn’t sat on the remote and changed the position – a nice little brain teaser when you get into 11 blinds that they want to independently operate. Whilst my logic is a work in progress; it’s very easy to integrate it into the UI.
I’ve just created a rule (still slightly WIP) to manage the blind moves and then I created a simple widget the provides the option to manage three sliders attached to proxy dimmers, each representing a group of blinds.
import org.openhab.core.model.script.ScriptServiceUtil
rule "Single Blind Instruction"
when
// A request to move a blind has probably come from the Room Location page
// A single blind has being requested rather than a Group of blinds
Member of BlindSingleMovement received update
then
val originalBlind = triggeringItem
val blindBaseName = triggeringItem.name.split("_").get(0)
logInfo("Somfy", "blindBaseName "+blindBaseName)
val somfyItem = ScriptServiceUtil.getItemRegistry.getItem(blindBaseName+"_Dimmer")
logInfo("Somfy", "somfyItem "+somfyItem.name)
val calibrationItem = ScriptServiceUtil.getItemRegistry.getItem(blindBaseName+"_Calibration")
logInfo("Somfy", "calibrationItem "+calibrationItem.name)
var int requiredPosition = (originalBlind.state as Number).intValue // get % dimmer and convert to number
var int currentPosition = (somfyItem.state as Number).intValue // get % dimmer and convert to number
var int blindTime = (calibrationItem.state as Number).intValue
var int speedSlot = (blindTime * 10) // eg 24 seconds top to bottom div 100 on slider * 1000 miliseconds
logInfo("Somfy", "Required Postion" + requiredPosition + " Current Postion " + currentPosition)
logInfo("Somfy", "Shutter " + triggeringItem.name + " Currently " + triggeringItem.state)
logInfo("Somfy", "Calibration Time " + blindTime + " Milliseconds per % movement " + speedSlot)
// Blinds can only be moved in 10% blocks
// Request for Blind to fully OPEN
if (( currentPosition < 100 ) && ( requiredPosition = 100 )) {
somfyItem.sendCommand(UP)
postUpdate(somfyItem, requiredPosition)
logInfo("Somfy", "Shutter " + triggeringItem.name + " going UP!")
// Request for Blind to fully CLOSE
} else if (( currentPosition > 0 ) && ( requiredPosition = 0 )) {
somfyItem.sendCommand(DOWN)
postUpdate(somfyItem, requiredPosition)
logInfo("Somfy", "Shutter " + triggeringItem.name + " going DOWN!")
} else if (( currentPosition > 79 ) && ( requiredPosition < 21 )) {
// then the Blind is NEARLY OPEN and it wants to go NEARLY CLOSED
logInfo("Somfy", "Blind " + triggeringItem.name + " Current Position " + currentPosition + " Taget Position " + requiredPosition )
logInfo("Somfy", "Using the opportunity to go DOWN via end point and resync")
// first go fully UP to resync
var int dimmerMovement = ( 100 - currentPosition ) * speedSlot
somfyItem.sendCommand(UP)
Thread::sleep(dimmerMovement)
logInfo("Somfy", "Moving to Fully Up, and going to wait 1 second before coming back down to Target")
logInfo("Somfy", "Expecting the first journey to take me " + dimmerMovement)
// wait 1 extra second
Thread::sleep(2000)
logInfo("Somfy", "I'm awake and i've headed back up a little as requested")
dimmerMovement = ( 100 - requiredPosition ) * speedSlot
somfyItem.sendCommand(DOWN)
Thread::sleep(dimmerMovement)
somfyItem.sendCommand(STOP)
} else if (( currentPosition < 21 ) && ( requiredPosition > 79 )) {
logInfo("Somfy", "Blind " + triggeringItem.name + " Current Position " + currentPosition + " Taget Position " + requiredPosition )
logInfo("Somfy", "Using the opportunity to go via end point and resync")
// first go fully DOWN
var int dimmerMovement = ( currentPosition ) * speedSlot
somfyItem.sendCommand(DOWN)
Thread::sleep(dimmerMovement)
logInfo("Somfy", "Moving to Fully DOWN, and going to wait 1 second before coming back down to Target")
logInfo("Somfy", "Expecting the first journey to take me " + dimmerMovement)
// wait 1 extra second
Thread::sleep(2000)
logInfo("Somfy", "I'm awake and i've headed down up a little as requested")
dimmerMovement = ( requiredPosition ) * speedSlot
somfyItem.sendCommand(UP)
Thread::sleep(dimmerMovement)
somfyItem.sendCommand(STOP)
} else if (requiredPosition > currentPosition) {
var int dimmerMovement = ( requiredPosition - currentPosition ) * speedSlot
logInfo("Somfy", "I'm a Blind called " + triggeringItem.name + " And I'm Currently here " + currentPosition + " and you want me here " + requiredPosition )
somfyItem.sendCommand(UP)
Thread::sleep(dimmerMovement)
somfyItem.sendCommand(STOP)
postUpdate(somfyItem, requiredPosition)
} else {
var int dimmerMovement = ( currentPosition - requiredPosition ) * speedSlot
logInfo("Somfy", "I'm a Blind called " + triggeringItem.name + " And I'm Currently here " + currentPosition + " and you want me here " + requiredPosition )
somfyItem.sendCommand(DOWN)
Thread::sleep(dimmerMovement)
somfyItem.sendCommand(STOP)
postUpdate(somfyItem, requiredPosition)
}
end
rule "Multiple Blind Group Move"
when
// A request to move a blind has probably come from the Room Location page
// A group blind has being requested rather than a Group of blinds
Member of BlindMultipleMovement received update
then
val originalBlind = triggeringItem
val blindBaseName = triggeringItem.name.split("_").get(0)
logInfo("Somfy", "Request for Multiple blind movement in Blind Group "+blindBaseName)
val requiredPosition = originalBlind.state.toString
blindBaseName.sendCommand(requiredPosition)
end
When the slider is moved; the Rule is executed.
And to hook it into the UI. I just added the widget parameters to the default Standalone & List item for that piece of Equipment (Kitchen Blind) and the respective Point (KitchenBlind_Control) - again, so so super easy in OH3!
So now whenever they go to that Room on the OH3 app, and look to move a blind they get the Schrödinger’s cat widget pop up automatically.
I’m just finishing off the widget logic; but happy to post that later.
I can see why you chose Thailand for your honeymoon, its an amazing country!