[OBSOLETE] Fibaro Roller Shutter 2 - FGRM-222 (DTH in post 24) (UK Device)

Hi julbmann

Nice device handler! It allows to calibrate device through smartthings. I’ve made a small change to correct % offset, as in my case, when I set level to 50%, it really sets level to 35%. Very simple change, just add a new parameter, and consider it in setLevel function:

input name: “percentageOffset”, type: “decimal”, title: “Percentage offset”, description: “The percentage offset to correct level”

def setLevel(level) {
if (invert) {
level = 100 - level
}

if(level > 99) level = 99

if (level <= (openOffset ?: 95) && level >= (closeOffset ?: 5)) {
    level = level - (percentageOffset ?: 0)
}
  
log.debug("set level ${level}")
delayBetween([
    zwave.basicV1.basicSet(value: level).format(),
    zwave.switchMultilevelV1.switchMultilevelGet().format()
], 10000)

}

1 Like

Hi Julien,

is it possible to add capability “Window Shade” in your dth? Or is there a reason why it should not? Thank you

yes, I think I can add this capacity. I will try to implement it this week.

2 Likes

@julbmann since you are going to work on this device handler, could you please correct the refresh problem??

Since I’ve changed to venetian roller shutter, it doesn’t refresh. I mean, I open the roller blind until the end, but in ST it says it’s still opening, and I can’t turn it off. To turn off the roller blind, I need to first press the Refresh button on ST for it to know that the roller blinds are 100% open.

Maybe is what @Gabriel_Diaz corrected?? Where in your code, can I implement his code??

Thanks you once again for this great device handler :slight_smile:

Hi capota. My fix doesn’t solve your problem. It just allows to correct open % error. For example, if you set it to 50% but it really opens at 35%, you can define an extra 15% offset through settings.

I’m not having sync issues, but as I see in julbmann device handler, the open status is checked every second. When your device reports “opening” or “closing”, what level % reports?. There are two settings that allows to specify what level % is considered in open status or in closed status, this might help you. By default, the device handler considers a level of (0%-5%) as closed status, and (95%-100%) as open status, but you can override this. For example, if your blinds are closed but it reports a level of 10%, you must set Close offset to 15%, if not, device handle will recognise status as “middle”.

Hi capota, I’ve just seen that two states might not be defined properly, as the next state of opening is defined as closing, and next state of closing, is defined as opening. Shouldn’t be opening -> open, and closing -> closed?

This is first device handler code that I see and edit, so my understanding about it is quite limited, but it might work.

Try attached code and let me know if helps, just two lines changed in bold:

metadata {
definition (name: “Fibaro Persianas Custom”, namespace: “julienbachmann”, author: “Julien Bachmann”) {
capability "Sensor"
capability "Actuator"
capability "Switch"
capability “Switch Level"
capability “Polling"
capability “Power Meter"
capability “Energy Meter"
capability “Refresh"
capability “Configuration"
attribute “openCloseStatus”, “enum”, [“open”, “middle”, “close”]
attribute “syncStatus”, “enum”, [“syncing”, “synced”]
command “open"
command “close"
command “sync"
fingerprint inClusters: “0x26,0x32”
}
tiles(scale: 2) {
multiAttributeTile(name:“mainTitle”, type:“generic”, width:6, height:4, canChangeIcon: true) {
tileAttribute(“device.openCloseStatus”, key: “PRIMARY_CONTROL”) {
attributeState “open”, label:‘Open’, backgroundColor:”#ffa81e”, action: “switch.off”, nextState: “closing"
attributeState “middle”, label:‘Middle’, backgroundColor:”#d45614”, action: “switch.on”, nextState: “opening"
attributeState “close”, label:‘Closed’, backgroundColor:”#00a0dc”, action: “switch.on”, nextState: “opening"
attributeState “opening”, label:‘Opening’, backgroundColor:"#ffa81e", nextState: "open"
attributeState “closing”, label:‘Closing’, backgroundColor:"#00a0dc", nextState: “close”
}
tileAttribute(“device.level”, key: “SLIDER_CONTROL”) {
attributeState “level”, action:“switch level.setLevel”, defaultState: true, icon:“st.Home.home9”
}
}
valueTile(“power”, “device.power”, width: 2, height: 2) {
state “default”, label:’${currentValue} W’
}
valueTile(“energy”, “device.energy”, width: 2, height: 2) {
state “default”, label:’${currentValue} kWh’
}
standardTile(“refresh”, “device.switch”, width: 2, height: 2, inactiveLabel: false, decoration: “flat”) {
state “default”, label:“Refresh”, action:“refresh.refresh”, icon:“st.secondary.refresh-icon”
}
standardTile(name: “calibrate”, width: 2, height: 2, decoration: “flat”) {
state “default”, action:“configuration.configure”, label:“Calibrate”, backgroundColor:”#0000a8
}
standardTile(“sync”, “device.syncStatus”, width: 2, height: 2, inactiveLabel: false, decoration: “flat”) {
state “default”, action:“sync” , label:“Sync”, backgroundColor:”#00a800"
state “synced”, action:“sync” , label:“Sync”, backgroundColor:”#00a800"
state “syncing” , label:“Syncing”, backgroundColor:”#a8a800
}
main([“mainTitle”])
details([“mainTitle”, “power”, “energy”, “refresh”, “calibrate”, “sync”])
}
preferences {
input name: “invert”, type: “bool”, title: “Invert up/down”, description: "Invert up and down actions"
input name: “openOffset”, type: “decimal”, title: “Open offset”, description: "The percentage from which shutter is displayerd as open"
input name: “closeOffset”, type: “decimal”, title: “Close offset”, description: "The percentage from which shutter is displayerd as close"
input name: “percentageOffset”, type: “decimal”, title: “Percentage offset”, description: "The percentage offset to correct level"
section {
input (
type: “paragraph”,
element: “paragraph”,
title: “DEVICE PARAMETERS:”,
description: "Device parameters are used to customise the physical device. " +
“Refer to the product documentation for a full description of each parameter.”
)
getParamsMd().findAll( {!it.readonly} ).each { // Exclude readonly parameters.
def lb = (it.description.length() > 0) ? “\n” : ""
switch(it.type) {
case “number”:
input (
name: “configParam${it.id}”,
title: “#${it.id}: ${it.name}: \n” + it.description + lb +“Default Value: ${it.defaultValue}”,
type: it.type,
range: it.range,
required: it.required
)
break
case “enum”:
input (
name: “configParam${it.id}”,
title: “#${it.id}: ${it.name}: \n” + it.description + lb + “Default Value: ${it.defaultValue}”,
type: it.type,
options: it.options,
required: it.required
)
break
}
}
} // section
}
}
def parse(String description) {
log.debug(“parse ${description}”)
def result = null
def cmd = zwave.parse(description, [0x20: 1, 0x26: 3, 0x70: 1, 0x32:3])
if (cmd) {
result = zwaveEvent(cmd)
if (result) {
log.debug(“Dispatch events ${result}”)
}
} else {
log.debug(“Couldn’t zwave.parse ${description}”)
}
result
}
def correctLevel(value) {
def result = value
if (value == “off”) {
result = 0;
}
if (value == “on” ) {
result = 100;
}
if (invert) {
result = 100 - result
}
return result
}
def createOpenCloseStatusEvent(value) {
def theOpenCloseStatus = “middle"
if (value >= (openOffset ?: 95)) {
theOpenCloseStatus = “open”
}
if (value <= (closeOffset ?: 5)) {
theOpenCloseStatus = “close”
}
return createEvent(name: “openCloseStatus”, value: theOpenCloseStatus, isStateChange: true)
}
def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicReport cmd) {
logger.debug(“basic report ${cmd}”)
def result = []
if (cmd.value != null) {
def level = correctLevel(cmd.value)
result << createEvent(name: “level”, value: level, unit: “%”, isStateChange: true)
result << createOpenCloseStatusEvent(level)
}
return result
}
def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicSet cmd) {
logger.debug(“basic set ${cmd}”)
def result = []
if (cmd.value) {
def level = correctLevel(cmd.value)
result << createEvent(name: “level”, value: level, unit: “%”, isStateChange: true)
result << createOpenCloseStatusEvent(level)
}
return result
}
def zwaveEvent(physicalgraph.zwave.commands.switchmultilevelv3.SwitchMultilevelStopLevelChange cmd) {
log.debug(“switch stop event ${cmd}”)
}
def zwaveEvent(physicalgraph.zwave.commands.switchmultilevelv3.SwitchMultilevelReport cmd) {
log.debug(“switch multi level report ${cmd.value}”)
def result = []
if (cmd.value != null) {
def level = correctLevel(cmd.value)
result << createEvent(name: “level”, value: level, unit: “%”, isStateChange: true)
result << createOpenCloseStatusEvent(level)
}
return result
}
def zwaveEvent(physicalgraph.zwave.Command cmd) {
log.debug(“other event ${cmd}”)
}
def zwaveEvent(physicalgraph.zwave.commands.meterv3.MeterReport cmd) {
if (cmd.meterType == 1) {
if (cmd.scale == 0) {
return createEvent(name: “energy”, value: cmd.scaledMeterValue, unit: “kWh”)
} else if (cmd.scale == 1) {
return createEvent(name: “energy”, value: cmd.scaledMeterValue, unit: “kVAh”)
} else if (cmd.scale == 2) {
return createEvent(name: “power”, value: Math.round(cmd.scaledMeterValue), unit: “W”)
} else {
return createEvent(name: “electric”, value: cmd.scaledMeterValue, unit: [“pulses”, “V”, “A”, “R/Z”, “”][cmd.scale - 3])
}
}
}
def zwaveEvent(physicalgraph.zwave.commands.configurationv1.ConfigurationReport cmd) {
log.debug(“zwaveEvent(): Configuration Report received: ${cmd}”)
}
def updated() {
setSynced();
}
def on() {
open()
}
def off() {
close()
}
def open() {
setLevel(100)
}
def close() {
setLevel(0)
}
def poll() {
delayBetween([
zwave.meterV2.meterGet(scale: 0).format(),
zwave.meterV2.meterGet(scale: 2).format(),
], 1000)
}
def refresh() {
log.debug(“refresh”)
delayBetween([
zwave.switchBinaryV1.switchBinaryGet().format(),
zwave.switchMultilevelV3.switchMultilevelGet().format(),
zwave.meterV2.meterGet(scale: 0).format(),
zwave.meterV2.meterGet(scale: 2).format(),
], 500)
}
def setLevel(level) {
if (invert) {
level = 100 - level
}
if(level > 99) level = 99
if (level <= (openOffset ?: 95) && level >= (closeOffset ?: 5)) {
level = level - (percentageOffset ?: 0)
}
log.debug(“set level ${level}”)
delayBetween([
zwave.basicV1.basicSet(value: level).format(),
zwave.switchMultilevelV1.switchMultilevelGet().format()
], 10000)
}
def configure() {
log.debug(“configure roller shutter”)
delayBetween([
zwave.configurationV1.configurationSet(parameterNumber: 29, size: 1, scaledConfigurationValue: 1).format(), // start calibration
zwave.switchMultilevelV1.switchMultilevelGet().format(),
zwave.meterV2.meterGet(scale: 0).format(),
zwave.meterV2.meterGet(scale: 2).format(),
], 500)
}
def sync() {
log.debug(“sync roller shutter”)
def cmds = []
sendEvent(name: “syncStatus”, value: “syncing”, isStateChange: true)
getParamsMd().findAll( {!it.readonly} ).each { // Exclude readonly parameters.
if (settings.“configParam${it.id}” != null) {
cmds << zwave.configurationV1.configurationSet(parameterNumber: it.id, size: it.size, scaledConfigurationValue: settings.“configParam${it.id}”.toInteger()).format()
cmds << zwave.configurationV1.configurationGet(parameterNumber: it.id).format()
}
}
log.debug(“send cmds ${cmds}”)
runIn(0.5 * cmds.size(), setSynced)
delayBetween(cmds, 500)
}
def setSynced() {
log.debug(“Synced”)
sendEvent(name: “syncStatus”, value: “synced”, isStateChange: true)
}
private getParamsMd() {
return [
[id: 3, size: 1, type: “number”, range: “0…1”, defaultValue: 0, required: false, readonly: false,
name: “Reports type”,
description: “0 – Blind position reports sent to the main controller using Z-Wave Command Class.\n” +
“1 - Blind position reports sent to the main controller using Fibar Command Class.\n” +
“Parameters value shoud be set to 1 if the module operates in Venetian Blind mode.”],
[id: 10, size: 1, type: “number”, range: “0…4”, defaultValue: 0, required: false, readonly: false,
name: “Roller Shutter operating modes”,
description: “0 - Roller Blind Mode, without positioning\n” +
“1 - Roller Blind Mode, with positioning\n” +
“2 - Venetian Blind Mode, with positioning\n” +
“3 - Gate Mode, without positioning\n” +
“4 - Gate Mode, with positioning”],
[id: 12, size:2, type: “number”, range: “0…65535”, defaultValue: 0, required: false, readonly: false,
name: “Time of full turn of the slat”,
description: “In Venetian Blind mode (parameter 10 set to 2) the parameter determines time of full turn of the slats.\n” +
“In Gate Mode (parameter 10 set to 3 or 4) the parameter defines the COUNTDOWN time, i.e. the time period after which an open gate starts closing. In any other operating mode the parameter value is irrelevant.\n” +
“Value of 0 means the gate will not close automatically.\n” +
“Available settings: 0-65535 (0 - 655,35s)\n” +
“Default setting: 150 (1,5 s)”],
[id: 13, size:1, type: “number”, range: “0…2”, defaultValue: 0, required: false, readonly: false,
name: “Set slats back to previous position”,
description: “In Venetian Blind Mode (parameter 10 set to 2) the parameter influences slats positioning in various situations. In any other operating mode the parameter value is irrelevant.\n” +
“0 - Slats return to previously set position only in case of the main controller operation\n” +
“1 - Slats return to previously set position in case of the main controller operation, momentary switch operation, or when the limit switch is reached.\n” +
“2 - Slats return to previously set position in case of the main controller operation, momentary switch operation, when the limit switch is reached or after " +
” receiving a “STOP” control frame (Switch Multilevel Stop).”],
[id: 14, size:1, type: “number”, range: “0…2”, defaultValue: 0, required: false, readonly: false,
name: “Switch type”,
description: “The parameter settings are relevant for Roller Blind Mode and Venetian Blind Mode (parameter 10 set to 0, 1, 2).\n” +
“0 - Momentary switches\n” +
“1 - Toggle switches\n” +
“2 - Single, momentary switch. (The switch should be connected to S1 terminal)”],
[id: 18, size:1, type: “number”, range: “0…255”, defaultValue: 0, required: false, readonly: false,
name: “Motor operation detection.”,
description: “Power threshold to be interpreted as reaching a limit switch. \n” +
“Available settings: 0 - 255 (1-255 W)\n” +
“The value of 0 means reaching a limit switch will not be detected \n” +
“Default setting: 10 (10W).”],
[id: 22, size:2, type: “number”, range: “0…65535”, defaultValue: 0, required: false, readonly: false,
name: “Motor operation time.”,
description: “Time period for the motor to continue operation. \n” +
“Available settings: 0 – 65535 (0 – 65535s)\n” +
“The value of 0 means the function is disabled.\n” +
“Default setting: 240 (240s. – 4 minutes)”],
[id: 30, size:1, type: “number”, range: “0…2”, defaultValue: 0, required: false, readonly: false,
name: “Response to general alarm”,
description: “0 - No reaction.\n” +
“1 - Open blind.\n” +
“2 - Close blind.”],
[id: 31, size:1, type: “number”, range: “0…2”, defaultValue: 0, required: false, readonly: false,
name: “Response to flooding alarm”,
description: “0 - No reaction.\n” +
“1 - Open blind.\n” +
“2 - Close blind.”],
[id: 32, size:1, type: “number”, range: “0…2”, defaultValue: 0, required: false, readonly: false,
name: “Response to smoke, CO or CO2 alarm”,
description: “0 - No reaction.\n” +
“1 - Open blind.\n” +
“2 - Close blind.”],
[id: 33, size:1, type: “number”, range: “0…2”, defaultValue: 0, required: false, readonly: false,
name: “Response to temperature alarm”,
description: “0 - No reaction.\n” +
“1 - Open blind.\n” +
“2 - Close blind.”],
[id: 35, size:1, type: “number”, range: “0…2”, defaultValue: 0, required: false, readonly: false,
name: “Managing slats in response to alarm.”,
description: “0 - Do not change slats position - slats return to the last set position\n” +
“1 - Set slats to their extreme position”]
]
}

I Gabriel,

Thanks for collaborating with me on this project. I think it is a good idea to add this extra parameter. But in your code you only take it into account in the setLevel function that is used to send state to the fibaro. And I think we should also use this offset in the correctLevel that is used when we receive percentage from the fibaro.

What do you think?

That would be perfect! I didn’t do it because I didn’t know where to place it. What function sends current level to the user?

What do you think about the nextState patch?

attributeState “opening”, label:‘Opening’, backgroundColor:"#ffa81e", nextState: "open"
attributeState “closing”, label:‘Closing’, backgroundColor:"#00a0dc", nextState: “close”

Is it correct? Or nextState was intended?

No, you are right, but I am not sure how nextState is used when you don’t have any action.

So I will do the change

1 Like

Any news on the changes julbmann? Thanks!

I push a new code on github. You can have a look. But as I didn’t have a lot of time I did not test it a lot. I hope I didn’t break anything.

Changes are:

  • add window shade capability
  • add offset pref
  • add up and down button (but for now I do not know how to stop the motor while it is running. So you cannot stop the motor at a specific positino with those button. You must use the level slider)

Let me know if you have any problem.

3 Likes

Hi Julien! Do you have a link to the code? I can’t seem to locate it on Github.

Thanks in advance. :slight_smile:

Yes, the link is on this post

link to repo

2 Likes

First of all, I have to thank you for the wonderful contribution!

Just wanna check with you, is there a way to let the slab of the venitian blinds open half way? Tried to fiddle around with the settings but none work.

Once again, Thanks !!!

Hi Julien,

As others I can’t calibrate my roller shutter (I guess due to missing feedback from the motor). Therefore I did install your device handler but I’m still having problems. Maybe you can help me?

My understanding was, that I could operate it (only open and close) without having to calibrate it, by setting all parameters to 0 except #22 to 25 (for 25 sec. that the rollers need to open/close). But after 25 sec. the LED of the shutter ist still red respetively green. Shouldn’t it go off? Did I understand something wrong with the parameters?

In the fibaro manual there is a parameter #17 mentioned (“determines when the relays are turned off after reaching a limit switch”). Do you have an idea if if that would turn the LED off? Could you add that parameter to your device handler?

Regards,
Jogi

Hi,
Ih ave installed FGRM-222 for two blinds, open and close works fine but partial is nor working ( has worked one time for one blind but now no more ).
I have tried calibration again but nothing.
Can you give me suggestion ?
Thanks for your support
Luigi

@julbmann

Hi Julien, First I would like to thank you indeed for your device handler for Fibaro FGR-222. I use Fibaro Roller Shutter FGR-221 v1.7, Roller Shutter 2 FGR-222 v2.2 and Roller Shutter 2 FGR-222 v2.5 in my house. Your device handler perfectly works with v2.2 and v2.5 (the only issue regarding v2.5 is ‘current state: on/off’ is missing on SmartThings IDE API/My Devices/ so it causes a question mark on ActionTiles https://support.actiontiles.com/forums/8-actiontiles-knowledge-base/topics/1038-question-mark-shown-on-virtual-switch-or-other-connected-thing-tile/ ) It works with FGR-221 v1.7 as well but there is a refresh issue; I need to push refresh in order to change the status from opening to open or closing to close on Smarttthings App otherwise App shows as opening or closing. I would appreciate if you could help us since you are the only device handler coder for Fibaro Roller Shutter. Regards

I have received information from Fibaro about the z-wave command I have to use for stopping the device. So I’ve just updated the device handler with following modifications:

  • Now if you click up or down when device is moving it will stop at current position. You can also click the main tile to stop it while it is opening or closing.
  • I fix some of state refresh issues.

You can get latest version on github:

3 Likes

Hi tayfunkucuk,

I do not understand your issue of question mark because I am not using this state for the tile. I am using the windowShade state. Could you check that you have it (the windowShade state) unser IDE API/My Devices/…

1 Like

@julbmann thank you for your prompt reply

please find attached screenshots of device details of FGR-221 v1.7, FGR-222 v2.2 and FGR-222 v2.5 on IDE. Current States/Switch are ON for v1.7s and v2.2s but it is missing for v2.5s so ActionTiles show it as a question mark since it needs the switch states ON or OFF @tgauchat

Regards




1 Like