OpenHAB MySensors binding 2.5: V_VAR1 and String values
-
Hello MySensors community.
I'm using OpenHAB MySensors binding 2.5 and would like to have my node (window cover controller) send a string on one of the V_VAR channels e.g. V_VAR5 back to the controller.
Intention:
Basically whenever I send a command to the node from the controller I intend to send a "reason" (or mode) to the node along with the command itself e.g. "Closed for sun protection" or "Closed for sleeping" or "Opened due to sunrise"...
This reason should be kept on the node and send beck to the controller on request e.g. after a restart of the controller (as a response to a message of type = C_REQ).
This way I could restart the controller and have it not only request cover positions but also the reason (or mode) that brought them into that position.Problem:
My problem with that is that apparently the OpenHAB MySensor binding does only support numeric values being transported from the nodes to the controller via V_VAR1 - V_VAR5 channels even though the Serial API of MySensors does allow string values for V_VAR1 to V_VAR5.Is there a solution to that problem, should the binding be changed?
How else could I achive what I'm trying to do?Here's the log entry of the request I'm sending from OpenHAB rule to the node:
2020-06-03 21:04:00.518 [DEBUG] [rsAbstractConnection$MySensorsWriter] - Sending to MySensors: 7;4;2;0;28;
And the log entries (errors) caused by the nodes response (the node sends the string "initial"):
2020-06-03 21:04:00.548 [DEBUG] [rsAbstractConnection$MySensorsReader] - Message from gateway received: 7;4;1;0;28;initial 2020-06-03 21:04:00.551 [DEBUG] [rs.internal.gateway.MySensorsGateway] - Node 7 found in gateway 2020-06-03 21:04:00.553 [DEBUG] [rs.internal.gateway.MySensorsGateway] - Child 4 found in node 7 2020-06-03 21:04:00.560 [ERROR] [nternal.event.MySensorsEventRegister] - Event broadcasting throw an exception java.lang.NumberFormatException: null at java.math.BigDecimal.<init>(BigDecimal.java:497) ~[?:1.8.0_252] at java.math.BigDecimal.<init>(BigDecimal.java:383) ~[?:1.8.0_252] at java.math.BigDecimal.<init>(BigDecimal.java:809) ~[?:1.8.0_252] at org.eclipse.smarthome.core.library.types.DecimalType.<init>(DecimalType.java:56) ~[?:?] at org.openhab.binding.mysensors.converter.MySensorsDecimalTypeConverter.fromString(MySensorsDecimalTypeConverter.java:31) ~[?:?] at org.openhab.binding.mysensors.converter.MySensorsTypeConverter.stateFromChannel(MySensorsTypeConverter.java:37) ~[?:?] at org.openhab.binding.mysensors.handler.MySensorsThingHandler.handleChildUpdateEvent(MySensorsThingHandler.java:301) ~[?:?] at org.openhab.binding.mysensors.handler.MySensorsThingHandler.sensorUpdateEvent(MySensorsThingHandler.java:221) ~[?:?] at org.openhab.binding.mysensors.internal.event.MySensorsEventRegister.lambda$4(MySensorsEventRegister.java:130) ~[?:?] at java.lang.Iterable.forEach(Iterable.java:75) ~[?:1.8.0_252] at org.openhab.binding.mysensors.internal.event.MySensorsEventRegister.notifyNodeUpdateEvent(MySensorsEventRegister.java:126) ~[?:?] at org.openhab.binding.mysensors.internal.gateway.MySensorsGateway.handleSetReqMessage(MySensorsGateway.java:564) ~[?:?] at org.openhab.binding.mysensors.internal.gateway.MySensorsGateway.handleIncomingMessage(MySensorsGateway.java:462) ~[?:?] at org.openhab.binding.mysensors.internal.gateway.MySensorsGateway.messageReceived(MySensorsGateway.java:375) ~[?:?] at org.openhab.binding.mysensors.internal.event.MySensorsEventRegister.lambda$1(MySensorsEventRegister.java:87) ~[?:?] at java.lang.Iterable.forEach(Iterable.java:75) [?:1.8.0_252] at org.openhab.binding.mysensors.internal.event.MySensorsEventRegister.notifyMessageReceived(MySensorsEventRegister.java:83) [bundleFile:?] at org.openhab.binding.mysensors.internal.protocol.MySensorsAbstractConnection$MySensorsReader.run(MySensorsAbstractConnection.java:362) [bundleFile:?] at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) [?:1.8.0_252] at java.util.concurrent.FutureTask.run(FutureTask.java:266) [?:1.8.0_252] at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [?:1.8.0_252] at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [?:1.8.0_252] at java.lang.Thread.run(Thread.java:748) [?:1.8.0_252]
Any help is highly appreciated.
Thanks and kind regards,
Ralph...
-
Just use the V_Var1-5 to send a number to the node ( saves bandwidth) and back then use the MAP transform function to shown the human readable strings.
Make sure you have the Map Transformation installed in Transformations add-ons
The add a mapping file in the transformation folder
example file blinds.map
NULL=unknown Reason -=unknown Reason 0=initial 1=Closed for Sunset 2=Closed for Sun Protection 3=Closed for Sleeping 4=Closed for Alexa Command 5=Closed for User Command 6=Closed for Security 7=Closed for Privacy 8=Closed for Migraine 9=Closed due to schedule 10 = Closed due to riots 33=Open for Sunrise 34=Open Ended Sun Protection 35=Open for Wakeup 36=Open for Alexa Command 37=Open for User Command 38=Open for Security 39=Open for No Privacy 40=Open for end of Migraine 41=Open due to schedule initial = 0 Closed for Sunset =1 Closed for Sun Protection = 2 Closed for Sleeping = 3 Closed for Alexa Command = 4 Closed for User Command = 5 Closed for Securitry = 6 Closed for Privacy = 7 Closed for Migraine = 8 Closed due to schedule = 9 Open for Sunrise = 33 Open Sun Protection Ended = 34 Open for Wakeup = 35 Open for Alexa Command = 36 Open for User Command = 37 Open for Securitry = 38 Open for No Privacy = 39 open end of Migraine = 40 open due to schedule = 41
add the map transformation to item
Sample Items
// Blind Nodes 234,235,236 Number Blinds1_Reason "Bedroom 1 Blinds [MAP(blinds.map):%s]" (blinds, test1) { channel = "mysensors:customSensor:gatewayWIFI2:Blinds234:var1" } Number Blinds2_Reason "Bedroom 2 Blinds [MAP(blinds.map):%s]" (blinds, test1) { channel = "mysensors:customSensor:gatewayWIFI2:Blinds235:var1" } Number Blinds3_Reason "Bedroom 3 Blinds [MAP(blinds.map):%s]" (blinds, test1) { channel = "mysensors:customSensor:gatewayW5100:Blinds236:var1" }
see https://www.openhab.org/addons/transformations/map/ for full details.
-
Thanks for pointing me into that direction - that seems like a feasable way to achieve what I'm looking for.
What I'm experiencing now though is when the node sends e.g. value 10 I get error:
java.lang.IllegalArgumentException: Value must be between 0 and 100
(see below for more log detail)
I changed the MySensors code on the node to divide the reason-code by 100 (e.g. 10 / 100) before sending it back the controller - that seems to be working (weird though).send(Jalousien[IncomingMessage.sensor - 1].MessageCommandReason.set(Jalousien[IncomingMessage.sensor - 1].CommandReason / 100.0, 0), false);
Next problem I'm facing is with the mapping. Even though I've "Map Transformation" installed the mapping as you suggested it does not really work for me.
Here's what I've tried so far (first entry should be exactly as you suggested):Items:
Number BueroRalphJalousieReason1 "Variant1 [MAP(blinds.map):%s]" { channel="mysensors:cover:gateway:BueroRalphJalousie:var5" } String BueroRalphJalousieReason2 "Variant2 [MAP(blinds.map):%s]" { channel="mysensors:cover:gateway:BueroRalphJalousie:var5" } String BueroRalphJalousieReason3 "Variant3 [%s]" (grp_Jalousien_SuedOstSeite_Reason) { channel="mysensors:cover:gateway:BueroRalphJalousie:var5" [profile="transform:MAP", function="blinds.map"] }
Mapping file blinds.map:
NULL=initial 0=initial 10=Closed for Sunset 11=Closed for Sun Protection 12=Closed for Sleeping 13=Closed for Alexa Command 14=Closed for User Command 15=Closed for Security 16=Closed for Privacy 17=Closed for Migraine 18=Closed due to schedule 30=Open for Sunrise 31=Open Ended Sun Protection 32=Open for Wakeup 33=Open for Alexa Command 34=Open for User Command 35=Open for Security 36=Open for No Privacy 37=Open for end of Migraine 38=Open due to schedule initial = 0 Closed for Sunset = 10 Closed for Sun Protection = 11 Closed for Sleeping = 12 Closed for Alexa Command = 13 Closed for User Command = 14 Closed for Securitry = 15 Closed for Privacy = 16 Closed for Migraine = 17 Closed due to schedule = 18 Open for Sunrise = 30 Open Sun Protection Ended = 31 Open for Wakeup = 32 Open for Alexa Command = 34 Open for User Command = 35 Open for Securitry = 36 Open for No Privacy = 37 open end of Migraine = 38 open due to schedule = 39
Result in Paper UI:
The only transformation working seems to be when applying the mapping to the channel (variant 3) - am I missing anything here?
Thanks and kind regards,
Ralph...Finally here's the detail on the error I'm getting realted to "Value must be between 0 and 100":
2020-06-05 12:50:00.755 [DEBUG] [rsAbstractConnection$MySensorsWriter] - Sending to MySensors: 7;4;2;0;28; 2020-06-05 12:50:00.787 [DEBUG] [rsAbstractConnection$MySensorsReader] - Message from gateway received: 7;4;1;0;28;10 2020-06-05 12:50:00.791 [DEBUG] [rs.internal.gateway.MySensorsGateway] - Node 7 found in gateway 2020-06-05 12:50:00.795 [DEBUG] [rs.internal.gateway.MySensorsGateway] - Child 4 found in node 7 2020-06-05 12:50:00.799 [DEBUG] [ensors.handler.MySensorsThingHandler] - Updating channel: var5(V_VAR5) value to: 10 2020-06-05 12:50:00.804 [ERROR] [nternal.event.MySensorsEventRegister] - Event broadcasting throw an exception java.lang.IllegalArgumentException: Value must be between 0 and 100 at org.eclipse.smarthome.core.library.types.PercentType.validateValue(PercentType.java:57) ~[?:?] at org.eclipse.smarthome.core.library.types.PercentType.<init>(PercentType.java:52) ~[?:?] at org.eclipse.smarthome.core.library.types.DecimalType.as(DecimalType.java:152) ~[?:?] at org.eclipse.smarthome.core.internal.items.ItemStateConverterImpl.convertToAcceptedState(ItemStateConverterImpl.java:64) ~[?:?] at org.eclipse.smarthome.core.thing.internal.profiles.ProfileCallbackImpl.sendUpdate(ProfileCallbackImpl.java:134) ~[?:?] at org.eclipse.smarthome.core.thing.internal.profiles.SystemDefaultProfile.onStateUpdateFromHandler(SystemDefaultProfile.java:53) ~[?:?] at org.eclipse.smarthome.core.thing.internal.CommunicationManager.lambda$9(CommunicationManager.java:467) ~[?:?] at org.eclipse.smarthome.core.thing.internal.CommunicationManager.lambda$11(CommunicationManager.java:487) ~[?:?] at java.lang.Iterable.forEach(Iterable.java:75) ~[?:1.8.0_252] at org.eclipse.smarthome.core.thing.internal.CommunicationManager.handleCallFromHandler(CommunicationManager.java:483) ~[?:?] at org.eclipse.smarthome.core.thing.internal.CommunicationManager.stateUpdated(CommunicationManager.java:465) ~[?:?] at org.eclipse.smarthome.core.thing.internal.ThingManagerImpl$1.stateUpdated(ThingManagerImpl.java:168) ~[?:?] at org.eclipse.smarthome.core.thing.binding.BaseThingHandler.updateState(BaseThingHandler.java:245) ~[?:?] at org.eclipse.smarthome.core.thing.binding.BaseThingHandler.updateState(BaseThingHandler.java:264) ~[?:?] at org.openhab.binding.mysensors.handler.MySensorsThingHandler.handleChildUpdateEvent(MySensorsThingHandler.java:305) ~[?:?] at org.openhab.binding.mysensors.handler.MySensorsThingHandler.sensorUpdateEvent(MySensorsThingHandler.java:221) ~[?:?] at org.openhab.binding.mysensors.internal.event.MySensorsEventRegister.lambda$4(MySensorsEventRegister.java:130) ~[?:?] at java.lang.Iterable.forEach(Iterable.java:75) ~[?:1.8.0_252] at org.openhab.binding.mysensors.internal.event.MySensorsEventRegister.notifyNodeUpdateEvent(MySensorsEventRegister.java:126) ~[?:?] at org.openhab.binding.mysensors.internal.gateway.MySensorsGateway.handleSetReqMessage(MySensorsGateway.java:564) ~[?:?] at org.openhab.binding.mysensors.internal.gateway.MySensorsGateway.handleIncomingMessage(MySensorsGateway.java:462) ~[?:?] at org.openhab.binding.mysensors.internal.gateway.MySensorsGateway.messageReceived(MySensorsGateway.java:375) ~[?:?] at org.openhab.binding.mysensors.internal.event.MySensorsEventRegister.lambda$1(MySensorsEventRegister.java:87) ~[?:?] at java.lang.Iterable.forEach(Iterable.java:75) [?:1.8.0_252] at org.openhab.binding.mysensors.internal.event.MySensorsEventRegister.notifyMessageReceived(MySensorsEventRegister.java:83) [bundleFile:?] at org.openhab.binding.mysensors.internal.protocol.MySensorsAbstractConnection$MySensorsReader.run(MySensorsAbstractConnection.java:362) [bundleFile:?] at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) [?:1.8.0_252] at java.util.concurrent.FutureTask.run(FutureTask.java:266) [?:1.8.0_252] at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [?:1.8.0_252] at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [?:1.8.0_252] at java.lang.Thread.run(Thread.java:748) [?:1.8.0_252]
To me the implementation of V_VAR handling in the openHAB mySensors binding seems odd - values for V_VAR1 thru V_VAR5 appear to be handled like percentage types where a 10 means 0.10.
I will try to send 0.10 instead of 10 from the node to the controller and my guess is that it will work then.
-
Dividing the value sent by the node to the controller by 100 did not help at all - still no way to send any value other than 0 or 1 back from the node to the controller.
Sending a 10 causes the error "Value must be between 0 and 100".No clue how to fix that - any help is highly appreciated!
The issue with the mapping within the item label not working on paper UI seems to be related to paper UI - apparently it does not support that type of mapping.
Showing the item value in HABpanel the mapping seems to be working fine.
-
I have tried this on my test system and i get the same results as you using the VAR1 -- VAR5 with the cover (RollerShutter) thing.
However if you add CustomSensor thing to your node then using the VAR1-VAR5 work as expected with the mapping. With numbers to and from the node.
things
cover Mock_Cover [nodeId=254, childId=6 ] text Mock_info [nodeId=254, childId=7 ]
Items
Rollershutter Mock_Cover_State "Mock Cover State [%s]" <rollershutter> (test254) { channel = "mysensors:cover:gatewayWIFI3:Mock_Cover:cover" } Number Mock_Info_Var1 "Mock Info Variable 1 (number) [%s]" (test254) { channel = "mysensors:text:gatewayWIFI3:Mock_Info:var1" } String Mock_Info_Var1s "Mock Info Variable 1 (string) [%s]" (test254) { channel = "mysensors:text:gatewayWIFI3:Mock_Info:var1" } Number Mock_Info_Var1m "Mock Info Variable 1 (number) [MAP(curtains.map):%s]" (test254) { channel = "mysensors:text:gatewayWIFI3:Mock_Info:var1" } String Mock_Info_Var1sm "Mock Info Variable 1 (string map) [%s]" (test254) { channel="mysensors:text:gatewayWIFI3:Mock_Info:var1" [profile="transform:MAP", function="curtains.map"] } Number Mock_Info_Var2 "Mock Info Variable 2 (number) [%s]" (test254) { channel = "mysensors:text:gatewayWIFI3:Mock_Info:var2" } Number Mock_Info_Var3 "Mock Info Variable 3 (number) [%s]" (test254) { channel = "mysensors:text:gatewayWIFI3:Mock_Info:var3" } Number Mock_Info_Var4 "Mock Info Variable 4 (number) [%s]" (test254) { channel = "mysensors:text:gatewayWIFI3:Mock_Info:var4" } Number Mock_Info_Var5 "Mock Info Variable 5 (number) [%s]" (test254) { channel = "mysensors:text:gatewayWIFI3:Mock_Info:var5" }
Node
#define CHILD_ID_COVER 6 #define CHILD_ID_CUSTOM 7 present(CHILD_ID_COVER, S_COVER, "Roller Shutters"); present(CHILD_ID_CUSTOM, S_CUSTOM, "Reasons");
Or you if you want to send strings you could use
String Mock_Info_Text "Mock Info text sting [%s] " (test254) { channel = "mysensors:text:gatewayWIFI3:Mock_Info:text" }