Modbus Binding block write (command) energy meter reset

I there

I am having trouble with a write block I need to send to a Schneider energy meter.

The meter is working
The binding is in place
I can see data from poller function and bind it to meaningful items, which seem real world (correct)

I can not reset the meter remotely with the function stated in the manual
I can write to a “command” register address the correct command number, as I can see the register that acknowledges the command and the register that returns an error: a “3002” which means the command block has invalid parameters.
The command is “2020” to register 5250, and that’s the only thing needed. But the command block has seven other registers (5251-5257) which are used to arguments and I believe they all must be zeroed.
So the commend aknowledged is “2020”, but with the error “3002 = Invalid number of parameters”

So I need a way to write in the same command multiple registers, all UInt16.

I read about the json write. It would be something like this, I believe:

[
    {
        "functionCode": 16,
        "address": 5249,
        "value": [2020, 0, 0, 0, 0, 0, 0, 0]
		"maxTries": 3
    }
]

But how would I send this to device?
#A data thing with a function - how to make this into a function to rewrite any string/number to this output?
#A rule with code output - how to integrate this into it?

I busted myself searching and trying and, for the most part, the binding is working, please help me with this bit.
Thanks!

I guess this is a Schneider meter, they do weird things.

yep, that looks good.

You need a data Thing defined, and you need to link it to an Item.
You specify a writeTransform on the channel, and have the transform output/return the JSON that you want.
You’d normally build that in javascript and use the JS transform.

If you wanted to change the JSON depending on what command you send to linked Item, that is done in the javascript transform.

To have it write to Modbus, you’d send a suitable command to your Item (i.e. suitable for whatever Item type you used).

I think this might get you started -

transform/meterreset.js

// variable "inputdata" contains command data passed by openhab
(function(inputData) {
   var obj = new Object();
   obj.functionCode = "16";
   obj.address = "5249";
   obj.value = "[ " + inputData + ", 0, 0, 0, 0, 0, 0, 0 ]"
   obj.maxTries = "3"
      //convert object to json string
   return JSON.stringify(obj);
})(input)

Thing for only this purpose, stick it under any meter poller

Thing data resetpm [ writeTransform="JS(meterreset.js)" ]

Item

Number MBresetmeter "reset register"  {channel="modbus:data:xxx:zzz:resetpm:number"}

Make it happen with MBresetmeter.sendCommand(2020)

I would be checking if it was decimal 2020 you were supposed to be sending though, not hex maybe.

2 Likes

Thank rossko57 you for your complete answer!

I have been trying to implement this. I must admit I always configured everything in paperUI, and with minor setbacks, that route went well.

My data thing for this purpose worked before. I was able to send and acknowledge the right command (status 3002 - right command invalid number of parameters). If I sent a 2021 I would get a 3000 response (invalid command)

I changed with the write transformation, after putting your code in /transform (meterreset.js)

This thing does not throw an error when I pass it data (before it would complain of not having either complete parameters or a JSON output)

I have two items which can pass a number or a string to the channel. I have been trying both. Before I could see the command given and the invalid number of parameters error in the feedback registers. Now it doe not change when I send data to the channel. If I remove the transformation it acknowledges the send again.

This is from the manual:



There is only one other command, to set communications:


But this is not needed, the meter is polling fine

Is there a way to check the output of the function, or the correct functioning of the javascript and JSONpath transformations services (the console shows them as “started”)

Thanks again for any input

You haven’t actually said what the problem is now. Still don’t know what the mystery target device is.

Writing registers defined as Slave ID, baud rate, etc. with zeros looks like a scary proposition. Slave ID = 0 is invalid in Modbus, so maybe it’s good that it doesn’t work…

By setting the Modbus binding log level, you can see what goes out on the bus.

Still don’t know what the mystery target device is.

Sorry about that:
The device is a Schneider iEM2155 modbus single phase meter

You haven’t actually said what the problem is now.

The problem is that the meter does not acknowledge the command received. If it is invalid I would expect a “3000” response. But the data channel remains online.

Writing registers defined as Slave ID, baud rate, etc. with zeros looks like a scary proposition. Slave ID = 0 is invalid in Modbus, so maybe it’s good that it doesn’t work…

I see what you mean. But this command (2020 in the first register) does not set communications. It is the only variable needed for resetting the meter. Still, the meter responds “invalid number of parameters” if I write only the first register. Is it possible or desirable to send empty values? like “”?

Thanks for the log tip:

11:10:52.252 [INFO ] [smarthome.event.ItemCommandEvent     ] - Item 'ShneiderModbusPartialResetActive_ValueAsString' received command 2020
11:10:52.266 [TRACE] [ternal.handler.ModbusDataThingHandler] - Thing modbus:data:d53556c9 'Shneider Modbus partial reset' received command '2020' to channel 'modbus:data:d53556c9:string'
11:10:52.278 [INFO ] [arthome.event.ItemStatePredictedEvent] - ShneiderModbusPartialResetActive_ValueAsString predicted to become 2020
11:10:52.360 [WARN ] [ternal.handler.ModbusDataThingHandler] - Thing modbus:data:d53556c9 'Shneider Modbus partial reset' could handle transformation result '{"functionCode":"16","address":"5249","value":"[ 2020, 0, 0, 0, 0, 0, 0, 0 ]","maxTries":"3"}'. Original command 2020. Error details follow
java.lang.IllegalStateException: This is not a JSON Array.
        at com.google.gson.JsonElement.getAsJsonArray(JsonElement.java:106) ~[21:com.google.gson:2.7.0.v20170129-0911]
        at org.openhab.io.transport.modbus.json.WriteRequestJsonUtilities.fromJson(WriteRequestJsonUtilities.java:97) ~[247:org.openhab.io.transport.modbus:2.5.0.M1]
        at org.openhab.binding.modbus.internal.handler.ModbusDataThingHandler.processJsonTransform(ModbusDataThingHandler.java:312) [246:org.openhab.binding.modbus:2.5.0.M1]
        at org.openhab.binding.modbus.internal.handler.ModbusDataThingHandler.transformCommandAndProcessJSON(ModbusDataThingHandler.java:242) [246:org.openhab.binding.modbus:2.5.0.M1]
        at org.openhab.binding.modbus.internal.handler.ModbusDataThingHandler.handleCommand(ModbusDataThingHandler.java:186) [246:org.openhab.binding.modbus:2.5.0.M1]
        at sun.reflect.GeneratedMethodAccessor66.invoke(Unknown Source) ~[?:?]
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:?]
        at java.lang.reflect.Method.invoke(Method.java:498) ~[?:?]
        at org.eclipse.smarthome.core.internal.common.AbstractInvocationHandler.invokeDirect(AbstractInvocationHandler.java:153) [102:org.eclipse.smarthome.core:0.11.0.oh250M1]
        at org.eclipse.smarthome.core.internal.common.InvocationHandlerSync.invoke(InvocationHandlerSync.java:59) [102:org.eclipse.smarthome.core:0.11.0.oh250M1]
        at com.sun.proxy.$Proxy136.handleCommand(Unknown Source) [246:org.openhab.binding.modbus:2.5.0.M1]
        at org.eclipse.smarthome.core.thing.internal.profiles.ProfileCallbackImpl.handleCommand(ProfileCallbackImpl.java:75) [109:org.eclipse.smarthome.core.thing:0.11.0.oh250M1]
        at org.eclipse.smarthome.core.thing.internal.profiles.SystemDefaultProfile.onCommandFromItem(SystemDefaultProfile.java:49) [109:org.eclipse.smarthome.core.thing:0.11.0.oh250M1]
        at sun.reflect.GeneratedMethodAccessor70.invoke(Unknown Source) ~[?:?]
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:?]
        at java.lang.reflect.Method.invoke(Method.java:498) ~[?:?]
        at org.eclipse.smarthome.core.internal.common.AbstractInvocationHandler.invokeDirect(AbstractInvocationHandler.java:153) [102:org.eclipse.smarthome.core:0.11.0.oh250M1]
        at org.eclipse.smarthome.core.internal.common.Invocation.call(Invocation.java:53) [102:org.eclipse.smarthome.core:0.11.0.oh250M1]
        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) [?:?]

So this looks like the function is not outputting the JSON… Maybe I made a mistake? I also installed Xpath…

Nope, if you write the register, you write the register. Modbus is simplistic (honestly!). The device might well reject/ignore of course.

This looks important.
I think what is missing is the array delimiters
Try this in the script

return "[ " + JSON.stringify(obj) + " ]"

;

1 Like

This note is not about that model I think, but very similar. Looks a bit scary, suggests you need to retrieve a “magic number” to allow reset.

So:
The code that got me going was:

// variable "inputdata" contains command data passed by openhab
(function(inputData) {
   var obj = new Object();
   obj.functionCode = 16;
   obj.address = 5249;
   obj.value = [ 2020, 0, 0, 0, 0, 0, 0, 0 ];
   obj.maxTries = 3
      //convert object to json string
   return "[ " + JSON.stringify(obj) + " ]"
})(input)

You may notice I made the input “2020” permanent. I had also to get the “” out of the parameters. Once I got the “” out I could not get the input “2020” to show in the string output. This way it stays there.

I am able to verify the command sent to the register is fine. No errors.

But… Still no joy. But the write works… If I change the string to [ 5000, 0, 0, 0, 1, 1, 0, 0, ] I am able to set communications and get a acknowledge “0” (Valid and successful command)! So your solution is working for the purpose of multiple register write!

Concerning the procedure you linked, I do not think it applies, it is not described in the manual.
I noticed this:


This is yet another table from the manual, and I noticed that the parameter addresses start two registers after the command, So I changed the registers to this:

// variable "inputdata" contains command data passed by openhab
(function(inputData) {
   var obj = new Object();
   obj.functionCode = 16;
   obj.address = 5249;
   obj.value = [ 2020, 0 ];
   obj.maxTries = 3
      //convert object to json string
   return "[ " + JSON.stringify(obj) + " ]"
})(input)

And success!!!
Response “0” to the command “2020” (given any input, obviously)
The meter is reset

So thank you very much!!!

1 Like

I’m not sure why the JSON didn’t work with “stringy” content - but then at this nuts and bolts protocol level everything is numeric, so maybe it’s not surprising.
EDIT - the binding doc does actually state that content should be numbers.

If you wanted some variable part, you’d parse it into a numeric in the javascript. (the incoming 2020 or whatever actually arrives in the script as string).

With a fixed payload, you may as well link the channel to a Switch type Item.

So in the end, you need to write just two registers in one hit? Turns out you could actually avoid all this transforming and configure a 32-bit data thing … :crazy_face:

1 Like

Yeah, You’re absolutely right. Let’s give a prize to the Schneider documentation!
Really, thanks for your help!

1 Like