Simulate a modbus tcp server and feed registers

hello,

until now I had a complete fronius environment, since yesterday I have a panel-based microinverter (hoymiles) and would like to give the fronius environment the data via modbus tcp.

there is a project which simulates with python and modbus-tcp a fronius-smartmeter which would be configureable on the fronius inverter as "production meter": fronius_sm_simulator/frsmsimulator.py at main · americanium/fronius_sm_simulator · GitHub

the hoymiles microinverter is attached with "opendtu", which runs on a ESP32. so, less http-requests to the esp32 would mean less load for the poor ESP.

as I already request the ESP32 with node red, I would like to process the data which is fetched with node red - and not an additional python script.

who can help me which nodes I need to add in node red to achieve a modbus tcp server to which the fronius device can connect and read the used registers?

data from the opendtu looks like the attached below.

as far as I can see, only "AC Power value (Total) [W]", "Total Watt Hours Exportet [Wh]" and "Total Watt Hours Imported [Wh]" need to be processed, also some header as kind of handshake needs to be sent.
the correct entries of the json attached would be: inverters[0].AC["0"].Power.v and total.YieldTotal.v

Thanks for any help on this. :slight_smile:

{"inverters":[{"serial":"138284652162","name":"Gartenhaus","data_age":1,"poll_enabled":true,"reachable":true,"producing":true,"limit_relative":100,"limit_absolute":2250,"AC":{"0":{"Power":{"v":66.5,"u":"W","d":1},"Voltage":{"v":413.1000061,"u":"V","d":1},"Current":{"v":0.090000004,"u":"A","d":2},"Power DC":{"v":69.80000305,"u":"W","d":1},"YieldDay":{"v":5663,"u":"Wh","d":0},"YieldTotal":{"v":17.19499969,"u":"kWh","d":3},"Frequency":{"v":49.95999908,"u":"Hz","d":2},"PowerFactor":{"v":1,"u":"","d":3},"ReactivePower":{"v":0,"u":"var","d":1},"Efficiency":{"v":95.27220154,"u":"%","d":3}}},"DC":{"0":{"name":{"u":""},"Power":{"v":7.699999809,"u":"W","d":1},"Voltage":{"v":28.10000038,"u":"V","d":1},"Current":{"v":0.270000011,"u":"A","d":2},"YieldDay":{"v":767,"u":"Wh","d":0},"YieldTotal":{"v":2.369999886,"u":"kWh","d":3}},"1":{"name":{"u":""},"Power":{"v":8.5,"u":"W","d":1},"Voltage":{"v":28.10000038,"u":"V","d":1},"Current":{"v":0.300000012,"u":"A","d":2},"YieldDay":{"v":742,"u":"Wh","d":0},"YieldTotal":{"v":2.259000063,"u":"kWh","d":3}},"2":{"name":{"u":""},"Power":{"v":14.10000038,"u":"W","d":1},"Voltage":{"v":32.59999847,"u":"V","d":1},"Current":{"v":0.430000007,"u":"A","d":2},"YieldDay":{"v":1087,"u":"Wh","d":0},"YieldTotal":{"v":3.487999916,"u":"kWh","d":3}},"3":{"name":{"u":""},"Power":{"v":13.80000019,"u":"W","d":1},"Voltage":{"v":32.59999847,"u":"V","d":1},"Current":{"v":0.419999987,"u":"A","d":2},"YieldDay":{"v":1065,"u":"Wh","d":0},"YieldTotal":{"v":3.15899992,"u":"kWh","d":3}},"4":{"name":{"u":""},"Power":{"v":12.89999962,"u":"W","d":1},"Voltage":{"v":28.39999962,"u":"V","d":1},"Current":{"v":0.449999988,"u":"A","d":2},"YieldDay":{"v":998,"u":"Wh","d":0},"YieldTotal":{"v":2.967000008,"u":"kWh","d":3}},"5":{"name":{"u":""},"Power":{"v":12.80000019,"u":"W","d":1},"Voltage":{"v":28.39999962,"u":"V","d":1},"Current":{"v":0.449999988,"u":"A","d":2},"YieldDay":{"v":1004,"u":"Wh","d":0},"YieldTotal":{"v":2.951999903,"u":"kWh","d":3}}},"INV":{"0":{"Temperature":{"v":23.20000076,"u":"°C","d":1}}},"events":10}],"total":{"Power":{"v":66.5,"u":"W","d":1},"YieldDay":{"v":5663,"u":"Wh","d":0},"YieldTotal":{"v":17.19499969,"u":"kWh","d":3}},"hints":{"time_sync":false,"radio_problem":false,"default_password":false}}

node-red-contrib-modbus includes a server, though I have not used it.

I could not find out yet how to correct feed data into modbus server, and also how to configure modbus server "correct".

configuration: I need a modbus server with registers 40000 to 40197. In Modbus Flex Server (and also Modbus Server) I can set Coils and Registers, but in both cases only the total amount. is it save to use "50000" registers, or will it need much more memory on the PI1 where it is running?

with the function below I would like to fill registers 40000 to 40197
if I do it (as in help text of the node mentioned) with setting a start address and then the values as comma-separated list, I receive an error:
"RangeError: The value of "value" is out of range. It must be >= 0 and <= 255. Received 396"

What does it want to tell me?

If I do it with the (commented out) for-loop, it is sent, but on processing the queue there show up:
"Is Not A Valid Memory Write Message To Server"

What does it want to tell me?

Thanks. :slight_smile:

BR
Alois

[{"id":"fd06b312dc398cd2","type":"inject","z":"62182fe8.227b8","name":"","props":[],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":90,"y":980,"wires":[["8cc340fc8a671cd3"]]},{"id":"8cc340fc8a671cd3","type":"function","z":"62182fe8.227b8","name":"Writeheaders","func":"var registers = [40000, 40001, 40002, 40003, 40004, 40005, 40006, 40007, 40008, 40009,\n    40010, 40011, 40012, 40013, 40014, 40015, 40016, 40017, 40018, 40019,\n    40020, 40021, 40022, 40023, 40024, 40025, 40026, 40027, 40028, 40029,\n    40030, 40031, 40032, 40033, 40034, 40035, 40036, 40037, 40038, 40039,\n    40040, 40041, 40042, 40043, 40044, 40045, 40046, 40047, 40048, 40049,\n    40050, 40051, 40052, 40053, 40054, 40055, 40056, 40057, 40058, 40059,\n    40060, 40061, 40062, 40063, 40064, 40065, 40066, 40067, 40068, 40069,\n    40070, 40071, 40072, 40073, 40074, 40075, 40076, 40077, 40078, 40079,\n    40080, 40081, 40082, 40083, 40084, 40085, 40086, 40087, 40088, 40089,\n    40090, 40091, 40092, 40093, 40094, 40095, 40096, 40097, 40098, 40099,\n    40100, 40101, 40102, 40103, 40104, 40105, 40106, 40107, 40108, 40109,\n    40110, 40111, 40112, 40113, 40114, 40115, 40116, 40117, 40118, 40119,\n    40120, 40121, 40122, 40123, 40124, 40125, 40126, 40127, 40128, 40129,\n    40130, 40131, 40132, 40133, 40134, 40135, 40136, 40137, 40138, 40139,\n    40140, 40141, 40142, 40143, 40144, 40145, 40146, 40147, 40148, 40149,\n    40150, 40151, 40152, 40153, 40154, 40155, 40156, 40157, 40158, 40159,\n    40160, 40161, 40162, 40163, 40164, 40165, 40166, 40167, 40168, 40169,\n    40170, 40171, 40172, 40173, 40174, 40175, 40176, 40177, 40178, 40179,\n    40180, 40181, 40182, 40183, 40184, 40185, 40186, 40187, 40188, 40189,\n    40190, 40191, 40192, 40193, 40194, 40195, 40196, 40197 ];\n\nvar values = [21365, 28243, 1, 65, 18034, 28526, 26997, 29440, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    21357, 24946, 29728, 19813, 29797, 29216, 21587, 8246, 13633, 11571, \n    0, 0, 0, 0, 0, 0, 15472, 29289, 28001, 29305,\n    15872, 0, 0, 0, 12590, 13056, 0, 0, 0, 0,\n    0, 0, 13111, 13111, 13111, 12851, 13360, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 204, 213,\n    124, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 65535, 0 ]\n\n// var functioncode = 16;\n// var startaddress = registers[0];\n// var addresses = registers.length;\n// msg.payload = { \"value\": values, 'fc': functioncode, 'unitid': 1, 'address': startaddress, 'quantity': addresses };\n\n// node.send(msg)\n\nfor (var i = 0; i < registers.length; i++) {\n    msg.payload = {\n        'value': values[i],\n        'fc': 6,\n        'unitid': 1,\n        'address': registers[i],\n        'quantity': 1\n    }\n    node.send(msg)\n}","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":270,"y":980,"wires":[["eb56533ecf4f4f3c","9d6bcedac60482aa"]]},{"id":"eb56533ecf4f4f3c","type":"modbus-flex-write","z":"62182fe8.227b8","name":"","showStatusActivities":true,"showErrors":true,"showWarnings":true,"server":"46f72e91930e4509","emptyMsgOnFail":false,"keepMsgProperties":false,"delayOnStart":false,"startDelayTime":"","x":510,"y":980,"wires":[["038f8b3b82a6eb4d"],[]]},{"id":"038f8b3b82a6eb4d","type":"modbus-flex-server","z":"62182fe8.227b8","name":"Node-Red-MB-Server","logEnabled":false,"serverAddress":"0.0.0.0","serverPort":"10502","responseDelay":100,"unitId":1,"delayUnit":"ms","coilsBufferSize":20000,"registersBufferSize":"50000","minAddress":0,"splitAddress":10000,"funcGetCoil":"function getFlexCoil(addr, unitID) {\n\tif (unitID === node.unitId && \n\t\taddr >= node.minAddress && \n\t\taddr <= node.splitAddress) { \n\n\t\treturn node.coils.readUInt8(addr * node.bufferFactor) \n\t}  \n}","funcGetDiscreteInput":"function getFlexDiscreteInput(addr, unitID) {\n\taddr += node.splitAddress\n\tif (unitID === node.unitId && \n\t\taddr >= node.splitAddress && \n\t\taddr <= node.splitAddress * 2) { \n\n\t\treturn node.coils.readUInt8(addr * node.bufferFactor) \n\t}  \n}","funcGetInputRegister":"function getFlexInputRegister(addr, unitID) { \n\tif (unitID === node.unitId && \n\t\taddr >= node.minAddress && \n\t\taddr <= node.splitAddress) { \n\n\t\treturn node.registers.readUInt16BE(addr * node.bufferFactor)  \n\t} \n}","funcGetHoldingRegister":"function getFlexHoldingRegsiter(addr, unitID) { \n\taddr += node.splitAddress\n\tif (unitID === node.unitId && \n\t\taddr >= node.splitAddress && \n\t\taddr <= node.splitAddress * 2) { \n\n\t\treturn node.registers.readUInt16BE(addr * node.bufferFactor)  \n\t} \n}","funcSetCoil":"function setFlexCoil(addr, value, unitID) { \n\tif (unitID === node.unitId && \n\t\taddr >= node.minAddress && \n\t\taddr <= node.splitAddress) { \n\n\t\tnode.coils.writeUInt8(value, addr * node.bufferFactor)  \n\t} \n}","funcSetRegister":"function setFlexRegister(addr, value, unitID) { \n\taddr += node.splitAddress\n\tif (unitID === node.unitId && \n\t\taddr >= node.splitAddress && \n\t\taddr <= node.splitAddress * 2) { \n\n\t\tnode.registers.writeUInt16BE(value, addr * node.bufferFactor)  \n\t} \n}","showErrors":true,"x":740,"y":980,"wires":[[],[],[],[],[]]},{"id":"9d6bcedac60482aa","type":"debug","z":"62182fe8.227b8","name":"debug 13","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":440,"y":1120,"wires":[]},{"id":"46f72e91930e4509","type":"modbus-client","name":"NodeRed-MB-Server","clienttype":"tcp","bufferCommands":true,"stateLogEnabled":false,"queueLogEnabled":false,"failureLogEnabled":true,"tcpHost":"127.0.0.1","tcpPort":"10502","tcpType":"DEFAULT","serialPort":"/dev/ttyUSB","serialType":"RTU-BUFFERD","serialBaudrate":"9600","serialDatabits":"8","serialStopbits":"1","serialParity":"none","serialConnectionDelay":"100","serialAsciiResponseStartDelimiter":"0x3A","unit_id":"1","commandDelay":"1","clientTimeout":"1000","reconnectOnTimeout":true,"reconnectTimeout":"2000","parallelUnitIdsAllowed":true,"showWarnings":true,"showLogs":true}]

That is part of you problem. You dont need to wire up the write request to the server.

Next, the registers 40000, 40001, 40002, ... should be addressed as 0, 1, 2, ...

Lastly, there is no need to write every one of the 198 items 1 at a time. Modbus can accept ~125 registers per write operation (depends on whether it is ASCII/RTU/TCP etc). As a rule, write no more than 100 in one go and you will be fine.

Here is a working demo:

chrome_7HD7WxvxXd

[{"id":"eb56533ecf4f4f3c","type":"modbus-flex-write","z":"eecddba75d36c6cd","name":"","showStatusActivities":true,"showErrors":true,"server":"5a03de1d4dae16b8","emptyMsgOnFail":false,"keepMsgProperties":false,"x":2290,"y":200,"wires":[[],[]]},{"id":"038f8b3b82a6eb4d","type":"modbus-flex-server","z":"eecddba75d36c6cd","name":"Node-Red-MB-Server","logEnabled":false,"serverAddress":"","serverPort":"10512","responseDelay":100,"unitId":1,"delayUnit":"ms","coilsBufferSize":20000,"registersBufferSize":"50000","minAddress":0,"splitAddress":10000,"funcGetCoil":"function getFlexCoil(addr, unitID) {\n\tif (unitID === node.unitId && \n\t\taddr >= node.minAddress && \n\t\taddr <= node.splitAddress) { \n\n\t\treturn node.coils.readUInt8(addr * node.bufferFactor) \n\t}  \n}","funcGetDiscreteInput":"function getFlexDiscreteInput(addr, unitID) {\n\taddr += node.splitAddress\n\tif (unitID === node.unitId && \n\t\taddr >= node.splitAddress && \n\t\taddr <= node.splitAddress * 2) { \n\n\t\treturn node.coils.readUInt8(addr * node.bufferFactor) \n\t}  \n}","funcGetInputRegister":"function getFlexInputRegister(addr, unitID) { \n\tif (unitID === node.unitId && \n\t\taddr >= node.minAddress && \n\t\taddr <= node.splitAddress) { \n\n\t\treturn node.registers.readUInt16BE(addr * node.bufferFactor)  \n\t} \n}","funcGetHoldingRegister":"function getFlexHoldingRegsiter(addr, unitID) { \n\taddr += node.splitAddress\n\tif (unitID === node.unitId && \n\t\taddr >= node.splitAddress && \n\t\taddr <= node.splitAddress * 2) { \n\n\t\treturn node.registers.readUInt16BE(addr * node.bufferFactor)  \n\t} \n}","funcSetCoil":"function setFlexCoil(addr, value, unitID) { \n\tif (unitID === node.unitId && \n\t\taddr >= node.minAddress && \n\t\taddr <= node.splitAddress) { \n\n\t\tnode.coils.writeUInt8(value, addr * node.bufferFactor)  \n\t} \n}","funcSetRegister":"function setFlexRegister(addr, value, unitID) { \n\taddr += node.splitAddress\n\tif (unitID === node.unitId && \n\t\taddr >= node.splitAddress && \n\t\taddr <= node.splitAddress * 2) { \n\n\t\tnode.registers.writeUInt16BE(value, addr * node.bufferFactor)  \n\t} \n}","showErrors":true,"x":2280,"y":100,"wires":[[],[],[],[],[]]},{"id":"f3b87e2c7eabb3bd","type":"inject","z":"eecddba75d36c6cd","name":"","props":[],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":1790,"y":200,"wires":[["6551034b0284c63e"]]},{"id":"6551034b0284c63e","type":"function","z":"eecddba75d36c6cd","name":"Write Headers (quicker)","func":"const registers = [40000, 40001, 40002, 40003, 40004, 40005, 40006, 40007, 40008, 40009,\n    40010, 40011, 40012, 40013, 40014, 40015, 40016, 40017, 40018, 40019,\n    40020, 40021, 40022, 40023, 40024, 40025, 40026, 40027, 40028, 40029,\n    40030, 40031, 40032, 40033, 40034, 40035, 40036, 40037, 40038, 40039,\n    40040, 40041, 40042, 40043, 40044, 40045, 40046, 40047, 40048, 40049,\n    40050, 40051, 40052, 40053, 40054, 40055, 40056, 40057, 40058, 40059,\n    40060, 40061, 40062, 40063, 40064, 40065, 40066, 40067, 40068, 40069,\n    40070, 40071, 40072, 40073, 40074, 40075, 40076, 40077, 40078, 40079,\n    40080, 40081, 40082, 40083, 40084, 40085, 40086, 40087, 40088, 40089,\n    40090, 40091, 40092, 40093, 40094, 40095, 40096, 40097, 40098, 40099,\n    40100, 40101, 40102, 40103, 40104, 40105, 40106, 40107, 40108, 40109,\n    40110, 40111, 40112, 40113, 40114, 40115, 40116, 40117, 40118, 40119,\n    40120, 40121, 40122, 40123, 40124, 40125, 40126, 40127, 40128, 40129,\n    40130, 40131, 40132, 40133, 40134, 40135, 40136, 40137, 40138, 40139,\n    40140, 40141, 40142, 40143, 40144, 40145, 40146, 40147, 40148, 40149,\n    40150, 40151, 40152, 40153, 40154, 40155, 40156, 40157, 40158, 40159,\n    40160, 40161, 40162, 40163, 40164, 40165, 40166, 40167, 40168, 40169,\n    40170, 40171, 40172, 40173, 40174, 40175, 40176, 40177, 40178, 40179,\n    40180, 40181, 40182, 40183, 40184, 40185, 40186, 40187, 40188, 40189,\n    40190, 40191, 40192, 40193, 40194, 40195, 40196, 40197 ];\n\nconst values = [21365, 28243, 1, 65, 18034, 28526, 26997, 29440, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    21357, 24946, 29728, 19813, 29797, 29216, 21587, 8246, 13633, 11571, \n    0, 0, 0, 0, 0, 0, 15472, 29289, 28001, 29305,\n    15872, 0, 0, 0, 12590, 13056, 0, 0, 0, 0,\n    0, 0, 13111, 13111, 13111, 12851, 13360, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 204, 213,\n    124, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 65535, 0 ]\n\nconst reg1 = registers.map(reg => reg - 40000)\nconst reg2 = reg1.splice(100)\nconst values2 = values.splice(100)\n\nconst p1 = {\n    'value': values,\n    'fc': 16,\n    'unitid': 1,\n    'address': reg1,\n    'quantity': values.length\n}\nconst p2 = {\n    'value': values2,\n    'fc': 16,\n    'unitid': 1,\n    'address': reg2,\n    'quantity': values2.length\n}\n\nnode.send({payload: p1})\nnode.send({payload: p2})\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":2010,"y":200,"wires":[["eb56533ecf4f4f3c"]]},{"id":"f4e2a505c51b636e","type":"modbus-flex-getter","z":"eecddba75d36c6cd","name":"","showStatusActivities":false,"showErrors":false,"logIOActivities":false,"server":"5a03de1d4dae16b8","useIOFile":false,"ioFile":"","useIOForPayload":false,"emptyMsgOnFail":false,"keepMsgProperties":false,"x":2010,"y":300,"wires":[["c05ef2bcd9f15d19"],[]]},{"id":"2c0401832b4e68a9","type":"inject","z":"eecddba75d36c6cd","name":"get 40000:10","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{\"fc\":3,\"unitid\":1,\"address\":0,\"quantity\":10}","payloadType":"json","x":1810,"y":300,"wires":[["f4e2a505c51b636e"]]},{"id":"c05ef2bcd9f15d19","type":"function","z":"eecddba75d36c6cd","name":"compare first 10","func":"const expectedValues = [21365, 28243, 1, 65, 18034, 28526, 26997, 29440, 0, 0]\nconst data = msg.payload\nlet result = '✅ Data matches'\nif (Array.isArray(data) == false) {\n    result = `Data Read not an array`\n} else if (data.length != expectedValues.length) {\n    result = `Data Read Length is ${data.length}. Expected ${expectedValues.length}`\n} else {\n    for (let index = 0; index < data.length; index++) {\n        const expected = expectedValues[index];\n        const readData = data[index];\n        if (expected !== readData) {\n            result = `Data at register ${40000 + index} is ${readData}. Expected ${expected}`\n            break\n        }\n    }\n}\nmsg.payload = {\n    result: result,\n    readData: data,\n    expected: expectedValues\n}\nreturn msg\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":2240,"y":300,"wires":[["2d5e5b1b1f33b9fb"]]},{"id":"2d5e5b1b1f33b9fb","type":"debug","z":"eecddba75d36c6cd","name":"debug 192","active":true,"tosidebar":true,"console":false,"tostatus":true,"complete":"payload","targetType":"msg","statusVal":"payload","statusType":"auto","x":2250,"y":360,"wires":[]},{"id":"941ffc08d2760e77","type":"inject","z":"eecddba75d36c6cd","name":"","props":[],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":1790,"y":240,"wires":[["d1e725ef2283421f"]]},{"id":"d1e725ef2283421f","type":"function","z":"eecddba75d36c6cd","name":"Clear headers","func":"\nconst ninetyNineZeros = []\nninetyNineZeros.length = 99\nninetyNineZeros.fill(0)\n\nconst p1 = {\n    'value': ninetyNineZeros,\n    'fc': 16,\n    'unitid': 1,\n    'address': 0,\n    'quantity': ninetyNineZeros.length\n}\nconst p2 = {\n    'value': ninetyNineZeros,\n    'fc': 16,\n    'unitid': 1,\n    'address': 99,\n    'quantity': ninetyNineZeros.length\n}\n\nnode.send({payload: p1})\nnode.send({payload: p2})\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1980,"y":240,"wires":[["eb56533ecf4f4f3c"]]},{"id":"5a03de1d4dae16b8","type":"modbus-client","name":"myServer 10512","clienttype":"tcp","bufferCommands":true,"stateLogEnabled":false,"queueLogEnabled":false,"failureLogEnabled":true,"tcpHost":"127.0.0.1","tcpPort":"10512","tcpType":"DEFAULT","serialPort":"/dev/ttyUSB","serialType":"RTU-BUFFERD","serialBaudrate":"9600","serialDatabits":"8","serialStopbits":"1","serialParity":"none","serialConnectionDelay":"100","serialAsciiResponseStartDelimiter":"0x3A","unit_id":"1","commandDelay":"1","clientTimeout":"1000","reconnectOnTimeout":true,"reconnectTimeout":"2000","parallelUnitIdsAllowed":true}]
1 Like

Hi Steve,

thanks, helped me already a lot.
Next, the registers 40000, 40001, 40002, ... should be addressed as 0, 1, 2, ...
I really need there registers 40000 and upwards, as the node-red-mb-server should emulate a fronius smart meter which offers exactly these registers I have in the map.
although I changed in the function:
//const reg1 = registers.map(reg => reg - 40000)
to
const reg1 = registers;

and the get-injector to
{"fc":3,"unitid":1,"address":40000,"quantity":10}

it currently does not look like it fills those registers.

any idea why?

Thank you again! :slightly_smiling_face:

Yes. Register 40000 is Hold Relay Register 0

Some implementations of modbus use the register value that is indexed from zero and leave off the leading numeral, but those implementations typically have you specify which Function Code FC will be used, so FC03 (read Holding registers) is used with (4)xxxxx addresses (sometimes without the leading numeral (4) or FC 04 (read input registers) is used with (3)xxxxx addresses.

okay, this means I cannot write to those registers?
I would need to get with this node an output of the "headers" (then I can compare them with the data of the original device which should match).

[{"id":"5b87a444ff086162","type":"modbus-read","z":"62182fe8.227b8","name":"NodeRed SM header [40001 bis 40193] [10s]","topic":"","showStatusActivities":false,"logIOActivities":false,"showErrors":false,"showWarnings":true,"unitid":"1","dataType":"HoldingRegister","adr":"40000","quantity":"71","rate":"10","rateUnit":"h","delayOnStart":false,"startDelayTime":"","server":"46f72e91930e4509","useIOFile":false,"ioFile":"","useIOForPayload":false,"emptyMsgOnFail":false,"x":210,"y":940,"wires":[[],["f91b2f6b95e08903"]]},{"id":"46f72e91930e4509","type":"modbus-client","name":"NodeRed-MB-Server","clienttype":"tcp","bufferCommands":true,"stateLogEnabled":false,"queueLogEnabled":false,"failureLogEnabled":true,"tcpHost":"127.0.0.1","tcpPort":"10502","tcpType":"DEFAULT","serialPort":"/dev/ttyUSB","serialType":"RTU-BUFFERD","serialBaudrate":"9600","serialDatabits":"8","serialStopbits":"1","serialParity":"none","serialConnectionDelay":"100","serialAsciiResponseStartDelimiter":"0x3A","unit_id":"1","commandDelay":"1","clientTimeout":"1000","reconnectOnTimeout":true,"reconnectTimeout":"2000","parallelUnitIdsAllowed":true,"showWarnings":true,"showLogs":true}]

I did that in my demo flow. Did you import it?

Also, this single node-you have posted - you are attempting to read "HoldingRegister","adr":"40000"

As i said previously:

I will try to make that a little clearer: Register 40000 IS THE SAME AS FC3 Register 0.

So make your read node read register 0, FC3.

Hi Steve,

yes I did import it, yes I saw it is working with the Modbus Flex Getter Node.

But, whatever I do, my fronius inverter, which needs to speak in the end with the node red modbus server, does currently nothing with it. So even in tcpdump I cannot see any action with the source of the inverter.

but, I know, it first checks the "header" and if I want to fetch them with a similar node, where I know it is working (the OpenDTU), and a similar node, which requests a real smart meter connected by modbus RTU on the inverter,
if I just swap the server in this node, it does request only zero's from the node red modbus server.

see here all my working nodes. the "Node Red SM Header" only receives 0's from the Node red server, while it receives data from the OpenDTU or from the Inverter Server.

The (working) OpenDTU one is here in code: OpenDTU-FroniusSM-MB/ModbusDtu.cpp at master · AloisKlingler/OpenDTU-FroniusSM-MB · GitHub

As I cannot change the implementation on the inverter, I need to adapt the node red server to act like the smartmeter. :slight_smile:

thanks for your patience and help. much appreciated.

[{"id":"f91b2f6b95e08903","type":"debug","z":"62182fe8.227b8","name":"Smartmeterdebug","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":790,"y":860,"wires":[]},{"id":"5bde98f4660b5950","type":"modbus-read","z":"62182fe8.227b8","name":"OpenDTU Smart-Meter [40071 bis 40193] [10s]","topic":"","showStatusActivities":false,"logIOActivities":false,"showErrors":false,"showWarnings":true,"unitid":"200","dataType":"HoldingRegister","adr":"40071","quantity":"121","rate":"10","rateUnit":"h","delayOnStart":false,"startDelayTime":"","server":"0b24fa689407e50a","useIOFile":false,"ioFile":"","useIOForPayload":false,"emptyMsgOnFail":false,"x":220,"y":740,"wires":[[],["f91b2f6b95e08903","e2aef7556c66e141"]]},{"id":"da41de80e9db33df","type":"modbus-read","z":"62182fe8.227b8","name":"Smart-Meter orig [40071 bis 40193] [10s]","topic":"","showStatusActivities":false,"logIOActivities":false,"showErrors":false,"showWarnings":true,"unitid":"200","dataType":"HoldingRegister","adr":"40071","quantity":"121","rate":"10","rateUnit":"h","delayOnStart":false,"startDelayTime":"","server":"bcc4229c.180ac","useIOFile":false,"ioFile":"","useIOForPayload":false,"emptyMsgOnFail":false,"x":200,"y":780,"wires":[[],["f91b2f6b95e08903","e2aef7556c66e141"]]},{"id":"e2aef7556c66e141","type":"function","z":"62182fe8.227b8","name":"Smart Meter","func":"msg.topic = \"Smartmeter-Data\"\nmsg.payload = {\n    Current_AC: parseFloat(msg.payload.buffer.readFloatBE(0, 1, 2, 3).toFixed(3)),\n    Current_AC_Phase_1: parseFloat(msg.payload.buffer.readFloatBE(4, 5, 6, 7).toFixed(3)),\n    Current_AC_Phase_2: parseFloat(msg.payload.buffer.readFloatBE(8, 9, 10, 11).toFixed(3)),\n    Current_AC_Phase_3: parseFloat(msg.payload.buffer.readFloatBE(12, 13, 14, 15).toFixed(3)),\n    Voltage_AC_Phase_Avg: parseFloat(msg.payload.buffer.readFloatBE(16, 17, 18, 19).toFixed(3)),\n    Voltage_AC_Phase_1: parseFloat(msg.payload.buffer.readFloatBE(20, 21, 22, 23).toFixed(3)),\n    Voltage_AC_Phase_2: parseFloat(msg.payload.buffer.readFloatBE(24, 25, 26, 27).toFixed(3)),\n    Voltage_AC_Phase_3: parseFloat(msg.payload.buffer.readFloatBE(28, 29, 30, 31).toFixed(3)),\n    Voltage_AC_PhaseToPhase_Avg: parseFloat(msg.payload.buffer.readFloatBE(32, 33, 34, 35).toFixed(3)),\n    Voltage_AC_PhaseToPhase_12: parseFloat(msg.payload.buffer.readFloatBE(36, 37, 38, 39).toFixed(3)),\n    Voltage_AC_PhaseToPhase_23: parseFloat(msg.payload.buffer.readFloatBE(40, 41, 42, 43).toFixed(3)),\n    Voltage_AC_PhaseToPhase_31: parseFloat(msg.payload.buffer.readFloatBE(44, 45, 46, 47).toFixed(3)),\n    Frequency_AC: parseFloat(msg.payload.buffer.readFloatBE(48, 49, 50, 51).toFixed(3)),\n    PowerReal_AC_Grid: parseFloat(msg.payload.buffer.readFloatBE(52, 53, 54, 55).toFixed(3)),\n    PowerReal_AC_Phase_1: parseFloat(msg.payload.buffer.readFloatBE(56, 57, 58, 59).toFixed(3)),\n    PowerReal_AC_Phase_2: parseFloat(msg.payload.buffer.readFloatBE(60, 61, 62, 63).toFixed(3)),\n    PowerReal_AC_Phase_3: parseFloat(msg.payload.buffer.readFloatBE(64, 65, 66, 67).toFixed(3)),\n    PowerApparent_AC: parseFloat(msg.payload.buffer.readFloatBE(68, 69, 70, 71).toFixed(3)),\n    PowerApparent_AC_Phase_1: parseFloat(msg.payload.buffer.readFloatBE(72, 73, 74, 75).toFixed(3)),\n    PowerApparent_AC_Phase_2: parseFloat(msg.payload.buffer.readFloatBE(76, 76, 77, 79).toFixed(3)),\n    PowerApparent_AC_Phase_3: parseFloat(msg.payload.buffer.readFloatBE(80, 81, 82, 83).toFixed(3)),\n    PowerReactive_AC: parseFloat(msg.payload.buffer.readFloatBE(84, 85, 86, 87).toFixed(3)),\n    PowerReactive_AC_Phase_1: parseFloat(msg.payload.buffer.readFloatBE(88, 89, 90, 91).toFixed(3)),\n    PowerReactive_AC_Phase_2: parseFloat(msg.payload.buffer.readFloatBE(92, 93, 94, 95).toFixed(3)),\n    PowerReactive_AC_Phase_3: parseFloat(msg.payload.buffer.readFloatBE(96, 97, 98, 99).toFixed(3)),\n    PowerFactor_AC: parseFloat(msg.payload.buffer.readFloatBE(100, 101, 102, 103).toFixed(3)),\n    PowerFactor_AC_Phase_1: parseFloat(msg.payload.buffer.readFloatBE(104, 105, 106, 107).toFixed(3)),\n    PowerFactor_AC_Phase_2: parseFloat(msg.payload.buffer.readFloatBE(108, 109, 110, 111).toFixed(3)),\n    PowerFactor_AC_Phase_3: parseFloat(msg.payload.buffer.readFloatBE(112, 113, 114, 115).toFixed(3)),\n    E_Grid_Exported: parseFloat(msg.payload.buffer.readFloatBE(116, 117, 118, 119).toFixed(3)),\n    // E_Grid_Exported_Phase_1: parseFloat(msg.payload.buffer.readFloatBE(120, 121, 122, 123).toFixed(3)),\n    // E_Grid_Exported_Phase_2: parseFloat(msg.payload.buffer.readFloatBE(124, 125, 126, 127).toFixed(3)),\n    // E_Grid_Exported_Phase_3: parseFloat(msg.payload.buffer.readFloatBE(128, 129, 130, 131).toFixed(3)),\n    E_Grid_Imported: parseFloat(msg.payload.buffer.readFloatBE(132, 133, 134, 135).toFixed(3)),\n    // E_Grid_Imported_Phase_1: parseFloat(msg.payload.buffer.readFloatBE(136, 137, 138, 139).toFixed(3)),\n    // E_Grid_Imported_Phase_2: parseFloat(msg.payload.buffer.readFloatBE(140, 141, 142, 143).toFixed(3)),\n    // E_Grid_Imported_Phase_3: parseFloat(msg.payload.buffer.readFloatBE(144, 145, 146, 147).toFixed(3)),\n}\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":610,"y":760,"wires":[["f91b2f6b95e08903"]]},{"id":"927e38fcec909060","type":"modbus-read","z":"62182fe8.227b8","name":"OpenDTU SM header [40001 bis 40193] [10s]","topic":"","showStatusActivities":false,"logIOActivities":false,"showErrors":false,"showWarnings":true,"unitid":"200","dataType":"HoldingRegister","adr":"40000","quantity":"71","rate":"10","rateUnit":"h","delayOnStart":false,"startDelayTime":"","server":"0b24fa689407e50a","useIOFile":false,"ioFile":"","useIOForPayload":false,"emptyMsgOnFail":false,"x":210,"y":860,"wires":[[],["f91b2f6b95e08903"]]},{"id":"be93264bc1832e75","type":"modbus-read","z":"62182fe8.227b8","name":"Smart-Meter orig header [40001 bis 40193] [10s]","topic":"","showStatusActivities":false,"logIOActivities":false,"showErrors":false,"showWarnings":true,"unitid":"200","dataType":"HoldingRegister","adr":"0","quantity":"40071","rate":"10","rateUnit":"h","delayOnStart":false,"startDelayTime":"","server":"bcc4229c.180ac","useIOFile":false,"ioFile":"","useIOForPayload":false,"emptyMsgOnFail":false,"x":220,"y":900,"wires":[[],["f91b2f6b95e08903"]]},{"id":"5b87a444ff086162","type":"modbus-read","z":"62182fe8.227b8","name":"NodeRed SM header [40001 bis 40193] [10s]","topic":"","showStatusActivities":false,"logIOActivities":false,"showErrors":false,"showWarnings":true,"unitid":"1","dataType":"HoldingRegister","adr":"40000","quantity":"71","rate":"10","rateUnit":"h","delayOnStart":false,"startDelayTime":"","server":"46f72e91930e4509","useIOFile":false,"ioFile":"","useIOForPayload":false,"emptyMsgOnFail":false,"x":210,"y":940,"wires":[[],["f91b2f6b95e08903"]]},{"id":"edde1ea7c76bb0d1","type":"modbus-read","z":"62182fe8.227b8","name":"NodeRed Smart-Meter [40071 bis 40193] [10s]","topic":"","showStatusActivities":false,"logIOActivities":false,"showErrors":false,"showWarnings":true,"unitid":"200","dataType":"HoldingRegister","adr":"40071","quantity":"121","rate":"10","rateUnit":"h","delayOnStart":false,"startDelayTime":"","server":"46f72e91930e4509","useIOFile":false,"ioFile":"","useIOForPayload":false,"emptyMsgOnFail":false,"x":210,"y":820,"wires":[[],["f91b2f6b95e08903","e2aef7556c66e141"]]},{"id":"eb56533ecf4f4f3c","type":"modbus-flex-write","z":"62182fe8.227b8","name":"","showStatusActivities":true,"showErrors":true,"showWarnings":true,"server":"46f72e91930e4509","emptyMsgOnFail":false,"keepMsgProperties":false,"delayOnStart":false,"startDelayTime":"","x":590,"y":1140,"wires":[[],[]]},{"id":"038f8b3b82a6eb4d","type":"modbus-flex-server","z":"62182fe8.227b8","name":"Node-Red-MB-Server","logEnabled":false,"serverAddress":"","serverPort":"10502","responseDelay":100,"unitId":1,"delayUnit":"ms","coilsBufferSize":20000,"registersBufferSize":"50000","minAddress":0,"splitAddress":10000,"funcGetCoil":"function getFlexCoil(addr, unitID) {\n\tif (unitID === node.unitId && \n\t\taddr >= node.minAddress && \n\t\taddr <= node.splitAddress) { \n\n\t\treturn node.coils.readUInt8(addr * node.bufferFactor) \n\t}  \n}","funcGetDiscreteInput":"function getFlexDiscreteInput(addr, unitID) {\n\taddr += node.splitAddress\n\tif (unitID === node.unitId && \n\t\taddr >= node.splitAddress && \n\t\taddr <= node.splitAddress * 2) { \n\n\t\treturn node.coils.readUInt8(addr * node.bufferFactor) \n\t}  \n}","funcGetInputRegister":"function getFlexInputRegister(addr, unitID) { \n\tif (unitID === node.unitId && \n\t\taddr >= node.minAddress && \n\t\taddr <= node.splitAddress) { \n\n\t\treturn node.registers.readUInt16BE(addr * node.bufferFactor)  \n\t} \n}","funcGetHoldingRegister":"function getFlexHoldingRegsiter(addr, unitID) { \n\taddr += node.splitAddress\n\tif (unitID === node.unitId && \n\t\taddr >= node.splitAddress && \n\t\taddr <= node.splitAddress * 2) { \n\n\t\treturn node.registers.readUInt16BE(addr * node.bufferFactor)  \n\t} \n}","funcSetCoil":"function setFlexCoil(addr, value, unitID) { \n\tif (unitID === node.unitId && \n\t\taddr >= node.minAddress && \n\t\taddr <= node.splitAddress) { \n\n\t\tnode.coils.writeUInt8(value, addr * node.bufferFactor)  \n\t} \n}","funcSetRegister":"function setFlexRegister(addr, value, unitID) { \n\taddr += node.splitAddress\n\tif (unitID === node.unitId && \n\t\taddr >= node.splitAddress && \n\t\taddr <= node.splitAddress * 2) { \n\n\t\tnode.registers.writeUInt16BE(value, addr * node.bufferFactor)  \n\t} \n}","showErrors":true,"x":580,"y":1040,"wires":[[],[],[],[],[]]},{"id":"f3b87e2c7eabb3bd","type":"inject","z":"62182fe8.227b8","name":"","props":[],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":90,"y":1140,"wires":[["6551034b0284c63e"]]},{"id":"6551034b0284c63e","type":"function","z":"62182fe8.227b8","name":"Write Headers (quicker)","func":"const registers = [40000, 40001, 40002, 40003, 40004, 40005, 40006, 40007, 40008, 40009,\n    40010, 40011, 40012, 40013, 40014, 40015, 40016, 40017, 40018, 40019,\n    40020, 40021, 40022, 40023, 40024, 40025, 40026, 40027, 40028, 40029,\n    40030, 40031, 40032, 40033, 40034, 40035, 40036, 40037, 40038, 40039,\n    40040, 40041, 40042, 40043, 40044, 40045, 40046, 40047, 40048, 40049,\n    40050, 40051, 40052, 40053, 40054, 40055, 40056, 40057, 40058, 40059,\n    40060, 40061, 40062, 40063, 40064, 40065, 40066, 40067, 40068, 40069,\n    40070, 40071, 40072, 40073, 40074, 40075, 40076, 40077, 40078, 40079,\n    40080, 40081, 40082, 40083, 40084, 40085, 40086, 40087, 40088, 40089,\n    40090, 40091, 40092, 40093, 40094, 40095, 40096, 40097, 40098, 40099,\n    40100, 40101, 40102, 40103, 40104, 40105, 40106, 40107, 40108, 40109,\n    40110, 40111, 40112, 40113, 40114, 40115, 40116, 40117, 40118, 40119,\n    40120, 40121, 40122, 40123, 40124, 40125, 40126, 40127, 40128, 40129,\n    40130, 40131, 40132, 40133, 40134, 40135, 40136, 40137, 40138, 40139,\n    40140, 40141, 40142, 40143, 40144, 40145, 40146, 40147, 40148, 40149,\n    40150, 40151, 40152, 40153, 40154, 40155, 40156, 40157, 40158, 40159,\n    40160, 40161, 40162, 40163, 40164, 40165, 40166, 40167, 40168, 40169,\n    40170, 40171, 40172, 40173, 40174, 40175, 40176, 40177, 40178, 40179,\n    40180, 40181, 40182, 40183, 40184, 40185, 40186, 40187, 40188, 40189,\n    40190, 40191, 40192, 40193, 40194, 40195, 40196, 40197 ];\n\nconst values = [21365, 28243, 1, 65, 18034, 28526, 26997, 29440, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    21357, 24946, 29728, 19813, 29797, 29216, 21587, 8246, 13633, 11571, \n    0, 0, 0, 0, 0, 0, 15472, 29289, 28001, 29305,\n    15872, 0, 0, 0, 12590, 13056, 0, 0, 0, 0,\n    0, 0, 13111, 13111, 13111, 12851, 13360, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 204, 213,\n    124, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 65535, 0 ]\n\nconst reg1 = registers.map(reg => reg - 40000)\n//const reg1 = registers;\nconst reg2 = reg1.splice(100)\nconst values2 = values.splice(100)\n\nconst p1 = {\n    'value': values,\n    'fc': 16,\n    'unitid': 1,\n    'address': reg1,\n    'quantity': values.length\n}\nconst p2 = {\n    'value': values2,\n    'fc': 16,\n    'unitid': 1,\n    'address': reg2,\n    'quantity': values2.length\n}\n\nnode.send({payload: p1})\nnode.send({payload: p2})\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":310,"y":1140,"wires":[["eb56533ecf4f4f3c"]]},{"id":"f4e2a505c51b636e","type":"modbus-flex-getter","z":"62182fe8.227b8","name":"","showStatusActivities":false,"showErrors":false,"showWarnings":true,"logIOActivities":false,"server":"46f72e91930e4509","useIOFile":false,"ioFile":"","useIOForPayload":false,"emptyMsgOnFail":false,"keepMsgProperties":false,"delayOnStart":false,"startDelayTime":"","x":310,"y":1240,"wires":[["c05ef2bcd9f15d19"],[]]},{"id":"2c0401832b4e68a9","type":"inject","z":"62182fe8.227b8","name":"get 40000:10","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{\"fc\":4,\"unitid\":1,\"address\":0,\"quantity\":10}","payloadType":"json","x":110,"y":1240,"wires":[["f4e2a505c51b636e"]]},{"id":"c05ef2bcd9f15d19","type":"function","z":"62182fe8.227b8","name":"compare first 10","func":"const expectedValues = [21365, 28243, 1, 65, 18034, 28526, 26997, 29440, 0, 0]\nconst data = msg.payload\nlet result = '✅ Data matches'\nif (Array.isArray(data) == false) {\n    result = `Data Read not an array`\n} else if (data.length != expectedValues.length) {\n    result = `Data Read Length is ${data.length}. Expected ${expectedValues.length}`\n} else {\n    for (let index = 0; index < data.length; index++) {\n        const expected = expectedValues[index];\n        const readData = data[index];\n        if (expected !== readData) {\n            result = `Data at register ${40000 + index} is ${readData}. Expected ${expected}`\n            break\n        }\n    }\n}\nmsg.payload = {\n    result: result,\n    readData: data,\n    expected: expectedValues\n}\nreturn msg\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":540,"y":1240,"wires":[["2d5e5b1b1f33b9fb"]]},{"id":"2d5e5b1b1f33b9fb","type":"debug","z":"62182fe8.227b8","name":"debug 192","active":true,"tosidebar":true,"console":false,"tostatus":true,"complete":"payload","targetType":"msg","statusVal":"payload","statusType":"auto","x":550,"y":1300,"wires":[]},{"id":"941ffc08d2760e77","type":"inject","z":"62182fe8.227b8","name":"","props":[],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":90,"y":1180,"wires":[["d1e725ef2283421f"]]},{"id":"d1e725ef2283421f","type":"function","z":"62182fe8.227b8","name":"Clear headers","func":"\nconst ninetyNineZeros = []\nninetyNineZeros.length = 99\nninetyNineZeros.fill(0)\n\nconst p1 = {\n    'value': ninetyNineZeros,\n    'fc': 16,\n    'unitid': 1,\n    'address': 0,\n    'quantity': ninetyNineZeros.length\n}\nconst p2 = {\n    'value': ninetyNineZeros,\n    'fc': 16,\n    'unitid': 1,\n    'address': 99,\n    'quantity': ninetyNineZeros.length\n}\n\nnode.send({payload: p1})\nnode.send({payload: p2})\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":280,"y":1180,"wires":[["eb56533ecf4f4f3c"]]},{"id":"0b24fa689407e50a","type":"modbus-client","name":"OpenDTU_MB","clienttype":"tcp","bufferCommands":true,"stateLogEnabled":false,"queueLogEnabled":false,"failureLogEnabled":true,"tcpHost":"192.168.0.247","tcpPort":"502","tcpType":"DEFAULT","serialPort":"/dev/ttyUSB","serialType":"RTU-BUFFERD","serialBaudrate":"9600","serialDatabits":"8","serialStopbits":"1","serialParity":"none","serialConnectionDelay":"100","serialAsciiResponseStartDelimiter":"0x3A","unit_id":"1","commandDelay":"1","clientTimeout":"1000","reconnectOnTimeout":true,"reconnectTimeout":"2000","parallelUnitIdsAllowed":true,"showWarnings":true,"showLogs":true},{"id":"bcc4229c.180ac","type":"modbus-client","name":"Fronius","clienttype":"tcp","bufferCommands":true,"stateLogEnabled":false,"queueLogEnabled":false,"failureLogEnabled":false,"tcpHost":"192.168.0.249","tcpPort":"502","tcpType":"DEFAULT","serialPort":"/dev/ttyUSB","serialType":"RTU-BUFFERD","serialBaudrate":"9600","serialDatabits":"8","serialStopbits":"1","serialParity":"none","serialConnectionDelay":"100","serialAsciiResponseStartDelimiter":"","unit_id":1,"commandDelay":1,"clientTimeout":1000,"reconnectOnTimeout":true,"reconnectTimeout":2000,"parallelUnitIdsAllowed":true},{"id":"46f72e91930e4509","type":"modbus-client","name":"NodeRed-MB-Server","clienttype":"tcp","bufferCommands":true,"stateLogEnabled":false,"queueLogEnabled":false,"failureLogEnabled":true,"tcpHost":"127.0.0.1","tcpPort":"10502","tcpType":"DEFAULT","serialPort":"/dev/ttyUSB","serialType":"RTU-BUFFERD","serialBaudrate":"9600","serialDatabits":"8","serialStopbits":"1","serialParity":"none","serialConnectionDelay":"100","serialAsciiResponseStartDelimiter":"0x3A","unit_id":"1","commandDelay":"1","clientTimeout":"1000","reconnectOnTimeout":true,"reconnectTimeout":"2000","parallelUnitIdsAllowed":true,"showWarnings":true,"showLogs":true}]

so, now I would have finished the complete parsing of the other inverter, including sending the modbus message to the registers.
the flows are attached, the function "Symo" has an object called "msg.inverterdata" in which is filled by the http response of the inverter.
the data is correctly stored now on the modbus server, but it is stored in registers 0 to 192 instead of 40000 to 40192

the flows "NodeRed SM header [40001 bis 40193] [10s]" and "NodeRed Smart-Meter [40071 bis 40193] [10s]" can read the registers starting from 0 and they then have the necessary data in there. as soon as they get the offset of 40000 they reply with 0's

I captured the other inverter in trying to fetch the modbus data - it requests register 40000 and 40001 and gets back 0's. (tcpdump attached here, filter for "modbus.reference_num == 40000 or modbus.regnum16 == 40000")

I would store it with fc3 and register 0 and as far as I can see it is in register 0 and not 40000

any help appreciated. :slight_smile:

[{"id":"f91b2f6b95e08903","type":"debug","z":"62182fe8.227b8","name":"Smartmeterdebug","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":710,"y":860,"wires":[]},{"id":"5bde98f4660b5950","type":"modbus-read","z":"62182fe8.227b8","name":"OpenDTU Smart-Meter [40071 bis 40193] [10s]","topic":"","showStatusActivities":false,"logIOActivities":false,"showErrors":false,"showWarnings":true,"unitid":"200","dataType":"HoldingRegister","adr":"40071","quantity":"121","rate":"10","rateUnit":"h","delayOnStart":false,"startDelayTime":"","server":"0b24fa689407e50a","useIOFile":false,"ioFile":"","useIOForPayload":false,"emptyMsgOnFail":false,"x":220,"y":800,"wires":[[],["f91b2f6b95e08903","e2aef7556c66e141"]]},{"id":"da41de80e9db33df","type":"modbus-read","z":"62182fe8.227b8","name":"Smart-Meter orig [40071 bis 40193] [10s]","topic":"","showStatusActivities":false,"logIOActivities":false,"showErrors":false,"showWarnings":true,"unitid":"200","dataType":"HoldingRegister","adr":"40071","quantity":"121","rate":"10","rateUnit":"h","delayOnStart":false,"startDelayTime":"","server":"bcc4229c.180ac","useIOFile":false,"ioFile":"","useIOForPayload":false,"emptyMsgOnFail":false,"x":200,"y":880,"wires":[[],["f91b2f6b95e08903","e2aef7556c66e141"]]},{"id":"e2aef7556c66e141","type":"function","z":"62182fe8.227b8","name":"Smart Meter parsing","func":"msg.topic = \"Smartmeter-Data\"\nmsg.payload = {\n    Current_AC: parseFloat(msg.payload.buffer.readFloatBE(0, 1, 2, 3).toFixed(3)),\n    Current_AC_Phase_1: parseFloat(msg.payload.buffer.readFloatBE(4, 5, 6, 7).toFixed(3)),\n    Current_AC_Phase_2: parseFloat(msg.payload.buffer.readFloatBE(8, 9, 10, 11).toFixed(3)),\n    Current_AC_Phase_3: parseFloat(msg.payload.buffer.readFloatBE(12, 13, 14, 15).toFixed(3)),\n    Voltage_AC_Phase_Avg: parseFloat(msg.payload.buffer.readFloatBE(16, 17, 18, 19).toFixed(3)),\n    Voltage_AC_Phase_1: parseFloat(msg.payload.buffer.readFloatBE(20, 21, 22, 23).toFixed(3)),\n    Voltage_AC_Phase_2: parseFloat(msg.payload.buffer.readFloatBE(24, 25, 26, 27).toFixed(3)),\n    Voltage_AC_Phase_3: parseFloat(msg.payload.buffer.readFloatBE(28, 29, 30, 31).toFixed(3)),\n    Voltage_AC_PhaseToPhase_Avg: parseFloat(msg.payload.buffer.readFloatBE(32, 33, 34, 35).toFixed(3)),\n    Voltage_AC_PhaseToPhase_12: parseFloat(msg.payload.buffer.readFloatBE(36, 37, 38, 39).toFixed(3)),\n    Voltage_AC_PhaseToPhase_23: parseFloat(msg.payload.buffer.readFloatBE(40, 41, 42, 43).toFixed(3)),\n    Voltage_AC_PhaseToPhase_31: parseFloat(msg.payload.buffer.readFloatBE(44, 45, 46, 47).toFixed(3)),\n    Frequency_AC: parseFloat(msg.payload.buffer.readFloatBE(48, 49, 50, 51).toFixed(3)),\n    PowerReal_AC_Grid: parseFloat(msg.payload.buffer.readFloatBE(52, 53, 54, 55).toFixed(3)),\n    PowerReal_AC_Phase_1: parseFloat(msg.payload.buffer.readFloatBE(56, 57, 58, 59).toFixed(3)),\n    PowerReal_AC_Phase_2: parseFloat(msg.payload.buffer.readFloatBE(60, 61, 62, 63).toFixed(3)),\n    PowerReal_AC_Phase_3: parseFloat(msg.payload.buffer.readFloatBE(64, 65, 66, 67).toFixed(3)),\n    PowerApparent_AC: parseFloat(msg.payload.buffer.readFloatBE(68, 69, 70, 71).toFixed(3)),\n    PowerApparent_AC_Phase_1: parseFloat(msg.payload.buffer.readFloatBE(72, 73, 74, 75).toFixed(3)),\n    PowerApparent_AC_Phase_2: parseFloat(msg.payload.buffer.readFloatBE(76, 76, 77, 79).toFixed(3)),\n    PowerApparent_AC_Phase_3: parseFloat(msg.payload.buffer.readFloatBE(80, 81, 82, 83).toFixed(3)),\n    PowerReactive_AC: parseFloat(msg.payload.buffer.readFloatBE(84, 85, 86, 87).toFixed(3)),\n    PowerReactive_AC_Phase_1: parseFloat(msg.payload.buffer.readFloatBE(88, 89, 90, 91).toFixed(3)),\n    PowerReactive_AC_Phase_2: parseFloat(msg.payload.buffer.readFloatBE(92, 93, 94, 95).toFixed(3)),\n    PowerReactive_AC_Phase_3: parseFloat(msg.payload.buffer.readFloatBE(96, 97, 98, 99).toFixed(3)),\n    PowerFactor_AC: parseFloat(msg.payload.buffer.readFloatBE(100, 101, 102, 103).toFixed(3)),\n    PowerFactor_AC_Phase_1: parseFloat(msg.payload.buffer.readFloatBE(104, 105, 106, 107).toFixed(3)),\n    PowerFactor_AC_Phase_2: parseFloat(msg.payload.buffer.readFloatBE(108, 109, 110, 111).toFixed(3)),\n    PowerFactor_AC_Phase_3: parseFloat(msg.payload.buffer.readFloatBE(112, 113, 114, 115).toFixed(3)),\n    E_Grid_Exported: parseFloat(msg.payload.buffer.readFloatBE(116, 117, 118, 119).toFixed(3)),\n    // E_Grid_Exported_Phase_1: parseFloat(msg.payload.buffer.readFloatBE(120, 121, 122, 123).toFixed(3)),\n    // E_Grid_Exported_Phase_2: parseFloat(msg.payload.buffer.readFloatBE(124, 125, 126, 127).toFixed(3)),\n    // E_Grid_Exported_Phase_3: parseFloat(msg.payload.buffer.readFloatBE(128, 129, 130, 131).toFixed(3)),\n    E_Grid_Imported: parseFloat(msg.payload.buffer.readFloatBE(132, 133, 134, 135).toFixed(3)),\n    // E_Grid_Imported_Phase_1: parseFloat(msg.payload.buffer.readFloatBE(136, 137, 138, 139).toFixed(3)),\n    // E_Grid_Imported_Phase_2: parseFloat(msg.payload.buffer.readFloatBE(140, 141, 142, 143).toFixed(3)),\n    // E_Grid_Imported_Phase_3: parseFloat(msg.payload.buffer.readFloatBE(144, 145, 146, 147).toFixed(3)),\n}\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":640,"y":760,"wires":[["f91b2f6b95e08903"]]},{"id":"927e38fcec909060","type":"modbus-read","z":"62182fe8.227b8","name":"OpenDTU SM header [40001 bis 40193] [10s]","topic":"","showStatusActivities":false,"logIOActivities":false,"showErrors":false,"showWarnings":true,"unitid":"200","dataType":"HoldingRegister","adr":"40000","quantity":"71","rate":"10","rateUnit":"h","delayOnStart":false,"startDelayTime":"","server":"0b24fa689407e50a","useIOFile":false,"ioFile":"","useIOForPayload":false,"emptyMsgOnFail":false,"x":210,"y":760,"wires":[[],["f91b2f6b95e08903"]]},{"id":"be93264bc1832e75","type":"modbus-read","z":"62182fe8.227b8","name":"Smart-Meter orig header [40001 bis 40193] [10s]","topic":"","showStatusActivities":false,"logIOActivities":false,"showErrors":false,"showWarnings":true,"unitid":"200","dataType":"HoldingRegister","adr":"0","quantity":"40071","rate":"10","rateUnit":"h","delayOnStart":false,"startDelayTime":"","server":"bcc4229c.180ac","useIOFile":false,"ioFile":"","useIOForPayload":false,"emptyMsgOnFail":false,"x":220,"y":840,"wires":[[],["f91b2f6b95e08903"]]},{"id":"5b87a444ff086162","type":"modbus-read","z":"62182fe8.227b8","name":"NodeRed SM header [40001 bis 40193] [10s]","topic":"","showStatusActivities":false,"logIOActivities":false,"showErrors":false,"showWarnings":true,"unitid":"3","dataType":"HoldingRegister","adr":"0","quantity":"71","rate":"10","rateUnit":"h","delayOnStart":false,"startDelayTime":"","server":"46f72e91930e4509","useIOFile":false,"ioFile":"","useIOForPayload":false,"emptyMsgOnFail":false,"x":210,"y":960,"wires":[[],["f91b2f6b95e08903"]]},{"id":"edde1ea7c76bb0d1","type":"modbus-read","z":"62182fe8.227b8","name":"NodeRed Smart-Meter [40071 bis 40193] [10s]","topic":"","showStatusActivities":false,"logIOActivities":false,"showErrors":false,"showWarnings":true,"unitid":"3","dataType":"HoldingRegister","adr":"71","quantity":"121","rate":"10","rateUnit":"h","delayOnStart":false,"startDelayTime":"","server":"46f72e91930e4509","useIOFile":false,"ioFile":"","useIOForPayload":false,"emptyMsgOnFail":false,"x":210,"y":1000,"wires":[[],["f91b2f6b95e08903","e2aef7556c66e141"]]},{"id":"eb56533ecf4f4f3c","type":"modbus-flex-write","z":"62182fe8.227b8","name":"","showStatusActivities":true,"showErrors":true,"showWarnings":true,"server":"46f72e91930e4509","emptyMsgOnFail":false,"keepMsgProperties":false,"delayOnStart":false,"startDelayTime":"","x":570,"y":1200,"wires":[[],[]]},{"id":"038f8b3b82a6eb4d","type":"modbus-flex-server","z":"62182fe8.227b8","name":"Node-Red-MB-Server","logEnabled":true,"serverAddress":"","serverPort":"502","responseDelay":100,"unitId":"3","delayUnit":"ms","coilsBufferSize":20000,"registersBufferSize":"50000","minAddress":0,"splitAddress":10000,"funcGetCoil":"function getFlexCoil(addr, unitID) {\n\tif (unitID === node.unitId && \n\t\taddr >= node.minAddress && \n\t\taddr <= node.splitAddress) { \n\n\t\treturn node.coils.readUInt8(addr * node.bufferFactor) \n\t}  \n}","funcGetDiscreteInput":"function getFlexDiscreteInput(addr, unitID) {\n\taddr += node.splitAddress\n\tif (unitID === node.unitId && \n\t\taddr >= node.splitAddress && \n\t\taddr <= node.splitAddress * 2) { \n\n\t\treturn node.coils.readUInt8(addr * node.bufferFactor) \n\t}  \n}","funcGetInputRegister":"function getFlexInputRegister(addr, unitID) { \n\tif (unitID === node.unitId && \n\t\taddr >= node.minAddress && \n\t\taddr <= node.splitAddress) { \n\n\t\treturn node.registers.readUInt16BE(addr * node.bufferFactor)  \n\t} \n}","funcGetHoldingRegister":"function getFlexHoldingRegsiter(addr, unitID) { \n\taddr += node.splitAddress\n\tif (unitID === node.unitId && \n\t\taddr >= node.splitAddress && \n\t\taddr <= node.splitAddress * 2) { \n\n\t\treturn node.registers.readUInt16BE(addr * node.bufferFactor)  \n\t} \n}","funcSetCoil":"function setFlexCoil(addr, value, unitID) { \n\tif (unitID === node.unitId && \n\t\taddr >= node.minAddress && \n\t\taddr <= node.splitAddress) { \n\n\t\tnode.coils.writeUInt8(value, addr * node.bufferFactor)  \n\t} \n}","funcSetRegister":"function setFlexRegister(addr, value, unitID) { \n\taddr += node.splitAddress\n\tif (unitID === node.unitId && \n\t\taddr >= node.splitAddress && \n\t\taddr <= node.splitAddress * 2) { \n\n\t\tnode.registers.writeUInt16BE(value, addr * node.bufferFactor)  \n\t} \n}","showErrors":true,"x":560,"y":1120,"wires":[[],[],[],[],[]]},{"id":"f3b87e2c7eabb3bd","type":"inject","z":"62182fe8.227b8","name":"","props":[],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":90,"y":1140,"wires":[["6551034b0284c63e"]]},{"id":"6551034b0284c63e","type":"function","z":"62182fe8.227b8","name":"Write Headers (quicker)","func":"const registers = [40000, 40001, 40002, 40003, 40004, 40005, 40006, 40007, 40008, 40009,\n    40010, 40011, 40012, 40013, 40014, 40015, 40016, 40017, 40018, 40019,\n    40020, 40021, 40022, 40023, 40024, 40025, 40026, 40027, 40028, 40029,\n    40030, 40031, 40032, 40033, 40034, 40035, 40036, 40037, 40038, 40039,\n    40040, 40041, 40042, 40043, 40044, 40045, 40046, 40047, 40048, 40049,\n    40050, 40051, 40052, 40053, 40054, 40055, 40056, 40057, 40058, 40059,\n    40060, 40061, 40062, 40063, 40064, 40065, 40066, 40067, 40068, 40069,\n    40070, 40071, 40072, 40073, 40074, 40075, 40076, 40077, 40078, 40079,\n    40080, 40081, 40082, 40083, 40084, 40085, 40086, 40087, 40088, 40089,\n    40090, 40091, 40092, 40093, 40094, 40095, 40096, 40097, 40098, 40099,\n    40100, 40101, 40102, 40103, 40104, 40105, 40106, 40107, 40108, 40109,\n    40110, 40111, 40112, 40113, 40114, 40115, 40116, 40117, 40118, 40119,\n    40120, 40121, 40122, 40123, 40124, 40125, 40126, 40127, 40128, 40129,\n    40130, 40131, 40132, 40133, 40134, 40135, 40136, 40137, 40138, 40139,\n    40140, 40141, 40142, 40143, 40144, 40145, 40146, 40147, 40148, 40149,\n    40150, 40151, 40152, 40153, 40154, 40155, 40156, 40157, 40158, 40159,\n    40160, 40161, 40162, 40163, 40164, 40165, 40166, 40167, 40168, 40169,\n    40170, 40171, 40172, 40173, 40174, 40175, 40176, 40177, 40178, 40179,\n    40180, 40181, 40182, 40183, 40184, 40185, 40186, 40187, 40188, 40189,\n    40190, 40191, 40192, 40193, 40194, 40195, 40196, 40197 ];\n\nconst values = [21365, 28243, 1, 65, 18034, 28526, 26997, 29440, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    21357, 24946, 29728, 19813, 29797, 29216, 21587, 8246, 13633, 11571, \n    0, 0, 0, 0, 0, 0, 15472, 29289, 28001, 29305,\n    15872, 0, 0, 0, 12590, 13056, 0, 0, 0, 0,\n    0, 0, 13111, 13111, 13111, 12851, 13360, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 204, 213,\n    124, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 65535, 0 ]\n\nconst reg1 = registers.map(reg => reg - 40000)\nconst reg2 = reg1.splice(100)\nconst values2 = values.splice(100)\n\nconst p1 = {\n    'value': values,\n    'fc': 16,\n    'unitid': 3,\n    'address': reg1,\n    'quantity': values.length\n}\nconst p2 = {\n    'value': values2,\n    'fc': 16,\n    'unitid': 3,\n    'address': reg2,\n    'quantity': values2.length\n}\n\nnode.send({payload: p1})\nnode.send({payload: p2})\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":310,"y":1140,"wires":[["eb56533ecf4f4f3c"]]},{"id":"f4e2a505c51b636e","type":"modbus-flex-getter","z":"62182fe8.227b8","name":"","showStatusActivities":false,"showErrors":false,"showWarnings":true,"logIOActivities":false,"server":"46f72e91930e4509","useIOFile":false,"ioFile":"","useIOForPayload":false,"emptyMsgOnFail":false,"keepMsgProperties":false,"delayOnStart":false,"startDelayTime":"","x":310,"y":1240,"wires":[["c05ef2bcd9f15d19"],[]]},{"id":"2c0401832b4e68a9","type":"inject","z":"62182fe8.227b8","name":"get 40000:10","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{\"fc\":3,\"unitid\":3,\"address\":0,\"quantity\":10}","payloadType":"json","x":110,"y":1240,"wires":[["f4e2a505c51b636e"]]},{"id":"c05ef2bcd9f15d19","type":"function","z":"62182fe8.227b8","name":"compare first 10","func":"const expectedValues = [21365, 28243, 1, 65, 18034, 28526, 26997, 29440, 0, 0]\nconst data = msg.payload\nlet result = '✅ Data matches'\nif (Array.isArray(data) == false) {\n    result = `Data Read not an array`\n} else if (data.length != expectedValues.length) {\n    result = `Data Read Length is ${data.length}. Expected ${expectedValues.length}`\n} else {\n    for (let index = 0; index < data.length; index++) {\n        const expected = expectedValues[index];\n        const readData = data[index];\n        if (expected !== readData) {\n            result = `Data at register ${40000 + index} is ${readData}. Expected ${expected}`\n            break\n        }\n    }\n}\nmsg.payload = {\n    result: result,\n    readData: data,\n    expected: expectedValues\n}\nreturn msg\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":540,"y":1240,"wires":[["2d5e5b1b1f33b9fb"]]},{"id":"2d5e5b1b1f33b9fb","type":"debug","z":"62182fe8.227b8","name":"debug 192","active":true,"tosidebar":true,"console":false,"tostatus":true,"complete":"payload","targetType":"msg","statusVal":"payload","statusType":"auto","x":530,"y":1280,"wires":[]},{"id":"941ffc08d2760e77","type":"inject","z":"62182fe8.227b8","name":"","props":[],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":90,"y":1180,"wires":[["d1e725ef2283421f"]]},{"id":"d1e725ef2283421f","type":"function","z":"62182fe8.227b8","name":"Clear headers","func":"\nconst ninetyNineZeros = []\nninetyNineZeros.length = 99\nninetyNineZeros.fill(0)\n\nconst p1 = {\n    'value': ninetyNineZeros,\n    'fc': 16,\n    'unitid': 3,\n    'address': 0,\n    'quantity': ninetyNineZeros.length\n}\nconst p2 = {\n    'value': ninetyNineZeros,\n    'fc': 16,\n    'unitid': 3,\n    'address': 99,\n    'quantity': ninetyNineZeros.length\n}\n\nnode.send({payload: p1})\nnode.send({payload: p2})\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":280,"y":1180,"wires":[["eb56533ecf4f4f3c"]]},{"id":"0e68cc98cc81a55c","type":"http request","z":"62182fe8.227b8","name":"Symo","method":"GET","ret":"obj","paytoqs":"ignore","url":"http://192.168.0.248/components/readable","tls":"","persist":false,"proxy":"","insecureHTTPParser":false,"authType":"","senderr":false,"headers":[],"x":230,"y":1100,"wires":[["faa7f37c48349fd2"]]},{"id":"faa7f37c48349fd2","type":"function","z":"62182fe8.227b8","name":"Symo","func":"msg.inverterdata = {\n    Current_AC: (parseFloat((msg.payload.Body.Data[\"131169\"].channels.Current_AC_Phase_1) + parseFloat(msg.payload.Body.Data[\"131169\"].channels.Current_AC_Phase_2) + parseFloat(msg.payload.Body.Data[\"131169\"].channels.Current_AC_Phase_3))*-1).toFixed(1),\n    Current_AC_Phase_1: parseFloat(msg.payload.Body.Data[\"131169\"].channels.Current_AC_Phase_1*-1).toFixed(1),\n    Current_AC_Phase_2: parseFloat(msg.payload.Body.Data[\"131169\"].channels.Current_AC_Phase_2*-1).toFixed(1),\n    Current_AC_Phase_3: parseFloat(msg.payload.Body.Data[\"131169\"].channels.Current_AC_Phase_3*-1).toFixed(1),\n    Voltage_AC_Phase_Avg: ((parseFloat(msg.payload.Body.Data[\"131169\"].channels.Voltage_AC_PhaseToPhase_12 + parseFloat(msg.payload.Body.Data[\"131169\"].channels.Voltage_AC_PhaseToPhase_23) + parseFloat(msg.payload.Body.Data[\"131169\"].channels.Voltage_AC_PhaseToPhase_31))) / 3).toFixed(1),\n    Voltage_AC_PhaseToPhase_12: parseFloat(msg.payload.Body.Data[\"131169\"].channels.Voltage_AC_PhaseToPhase_12).toFixed(1),\n    Voltage_AC_PhaseToPhase_23: parseFloat(msg.payload.Body.Data[\"131169\"].channels.Voltage_AC_PhaseToPhase_23).toFixed(1),\n    Voltage_AC_PhaseToPhase_31: parseFloat(msg.payload.Body.Data[\"131169\"].channels.Voltage_AC_PhaseToPhase_31).toFixed(1),\n    Voltage_AC_PhaseToPhase_Avg: ((parseFloat(msg.payload.Body.Data[\"131169\"].channels.Voltage_AC_Phase_1) + parseFloat(msg.payload.Body.Data[\"131169\"].channels.Voltage_AC_Phase_2) + parseFloat(msg.payload.Body.Data[\"131169\"].channels.Voltage_AC_Phase_3)) / 3).toFixed(1),\n    Voltage_AC_Phase_1: parseFloat(msg.payload.Body.Data[\"131169\"].channels.Voltage_AC_Phase_1).toFixed(1),\n    Voltage_AC_Phase_2: parseFloat(msg.payload.Body.Data[\"131169\"].channels.Voltage_AC_Phase_2).toFixed(1),\n    Voltage_AC_Phase_3: parseFloat(msg.payload.Body.Data[\"131169\"].channels.Voltage_AC_Phase_3).toFixed(1),\n    Frequency_Phase_Average: parseFloat(msg.payload.Body.Data[\"131169\"].channels.Frequency_Phase_Average).toFixed(1),\n    PowerReal_AC_Grid: parseFloat(msg.payload.Body.Data[\"131169\"].channels.PowerReal_PAC_Sum*-1).toFixed(1),\n    PowerReal_AC_Phase_1: (parseFloat((msg.payload.Body.Data[\"131169\"].channels.Current_AC_Phase_1 * msg.payload.Body.Data[\"131169\"].channels.Voltage_AC_PhaseToPhase_12))*-1).toFixed(1),\n    PowerReal_AC_Phase_2: (parseFloat((msg.payload.Body.Data[\"131169\"].channels.Current_AC_Phase_2 * msg.payload.Body.Data[\"131169\"].channels.Voltage_AC_PhaseToPhase_23))*-1).toFixed(1),\n    PowerReal_AC_Phase_3: (parseFloat((msg.payload.Body.Data[\"131169\"].channels.Current_AC_Phase_3 * msg.payload.Body.Data[\"131169\"].channels.Voltage_AC_PhaseToPhase_31))*-1).toFixed(1),\n    PowerApparent_AC: 0,\n    PowerApparent_AC_Phase_1: 0,\n    PowerApparent_AC_Phase_2: 0,\n    PowerApparent_AC_Phase_3: 0,\n    PowerReactive_AC: 0,\n    PowerReactive_AC_Phase_1: 0,\n    PowerReactive_AC_Phase_2: 0,\n    PowerReactive_AC_Phase_3: 0,\n    PowerFactor_AC: 1,\n    PowerFactor_AC_Phase_1: 1,\n    PowerFactor_AC_Phase_2: 1,\n    PowerFactor_AC_Phase_3: 1,\n    E_Grid_Exported: parseInt(msg.payload.Body.Data[\"131169\"].channels.EnergyReal_WAC_Sum_EverSince) || 0,\n    E_Grid_Exported_Phase_1: 0,\n    E_Grid_Exported_Phase_2: 0,\n    E_Grid_Exported_Phase_3: 0,\n    E_Grid_Imported: 0,\n    E_Grid_Imported_Phase_1: 0,\n    E_Grid_Imported_Phase_2: 0,\n    E_Grid_Imported_Phase_3: 0\n}\n\nfunction tofloatregisters(value) {\n    var buf = Buffer.alloc(4);\n    buf.writeFloatBE(value);\n    return [(buf[0] * 256 + buf[1]), (buf[2] * 256) + buf[3]]\n}\n\nvar registers = [];\nvar values = [];\nvar i = 71;\n\nfor (var key of Object.keys(msg.inverterdata)) {\n    registers.push(i, i + 1)\n    for (var val of tofloatregisters(msg.inverterdata[key])) values.push(val);\n    i = i + 2;\n}\n\nconst modbusmessage = {\n    'value': values,\n    'fc': 16,\n    'unitid': 3,\n    'address': registers,\n    'quantity': values.length\n}\n\nreturn ({ payload: modbusmessage })","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":350,"y":1100,"wires":[["eb56533ecf4f4f3c"]]},{"id":"988f89c42b4c7488","type":"inject","z":"62182fe8.227b8","name":"","props":[],"repeat":"5","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":90,"y":1100,"wires":[["0e68cc98cc81a55c"]]},{"id":"0b24fa689407e50a","type":"modbus-client","name":"OpenDTU_MB","clienttype":"tcp","bufferCommands":true,"stateLogEnabled":false,"queueLogEnabled":false,"failureLogEnabled":true,"tcpHost":"192.168.0.247","tcpPort":"502","tcpType":"DEFAULT","serialPort":"/dev/ttyUSB","serialType":"RTU-BUFFERD","serialBaudrate":"9600","serialDatabits":"8","serialStopbits":"1","serialParity":"none","serialConnectionDelay":"100","serialAsciiResponseStartDelimiter":"0x3A","unit_id":"1","commandDelay":"1","clientTimeout":"1000","reconnectOnTimeout":true,"reconnectTimeout":"2000","parallelUnitIdsAllowed":true,"showWarnings":true,"showLogs":true},{"id":"bcc4229c.180ac","type":"modbus-client","name":"Fronius","clienttype":"tcp","bufferCommands":true,"stateLogEnabled":false,"queueLogEnabled":false,"failureLogEnabled":false,"tcpHost":"192.168.0.249","tcpPort":"502","tcpType":"DEFAULT","serialPort":"/dev/ttyUSB","serialType":"RTU-BUFFERD","serialBaudrate":"9600","serialDatabits":"8","serialStopbits":"1","serialParity":"none","serialConnectionDelay":"100","serialAsciiResponseStartDelimiter":"","unit_id":1,"commandDelay":1,"clientTimeout":1000,"reconnectOnTimeout":true,"reconnectTimeout":2000,"parallelUnitIdsAllowed":true},{"id":"46f72e91930e4509","type":"modbus-client","name":"NodeRed-MB-Server","clienttype":"tcp","bufferCommands":true,"stateLogEnabled":false,"queueLogEnabled":false,"failureLogEnabled":true,"tcpHost":"127.0.0.1","tcpPort":"502","tcpType":"DEFAULT","serialPort":"/dev/ttyUSB","serialType":"RTU-BUFFERD","serialBaudrate":"9600","serialDatabits":"8","serialStopbits":"1","serialParity":"none","serialConnectionDelay":"100","serialAsciiResponseStartDelimiter":"0x3A","unit_id":"3","commandDelay":"1","clientTimeout":"1000","reconnectOnTimeout":true,"reconnectTimeout":"2000","parallelUnitIdsAllowed":true,"showWarnings":true,"showLogs":true}]

fronius.zip.txt (2.4 KB)

Hi @Cyber

I am struggling to follow along since I do not have access to your hardware and from the pcap, I dont know which device is which.

Hopefully a second demo will help.

Here you can see I write to the node-red modbus server at addresses 0 and 40000 (which as I explained before it equivelanct to 4xxxx and 4xxxxx) but hey ho - if the client is really asking for 440000 address, who am i to argue.

Here is the updated example.
chrome_Jo4Sl09g08

And the flow...

[{"id":"eb56533ecf4f4f3c","type":"modbus-flex-write","z":"eecddba75d36c6cd","name":"","showStatusActivities":true,"showErrors":true,"server":"5a03de1d4dae16b8","emptyMsgOnFail":false,"keepMsgProperties":false,"x":2290,"y":200,"wires":[[],[]]},{"id":"f3b87e2c7eabb3bd","type":"inject","z":"eecddba75d36c6cd","name":"","props":[],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":1790,"y":200,"wires":[["6551034b0284c63e"]]},{"id":"6551034b0284c63e","type":"function","z":"eecddba75d36c6cd","name":"Write Headers to 4x0000 (quicker)","func":"const registers = [40000, 40001, 40002, 40003, 40004, 40005, 40006, 40007, 40008, 40009,\n    40010, 40011, 40012, 40013, 40014, 40015, 40016, 40017, 40018, 40019,\n    40020, 40021, 40022, 40023, 40024, 40025, 40026, 40027, 40028, 40029,\n    40030, 40031, 40032, 40033, 40034, 40035, 40036, 40037, 40038, 40039,\n    40040, 40041, 40042, 40043, 40044, 40045, 40046, 40047, 40048, 40049,\n    40050, 40051, 40052, 40053, 40054, 40055, 40056, 40057, 40058, 40059,\n    40060, 40061, 40062, 40063, 40064, 40065, 40066, 40067, 40068, 40069,\n    40070, 40071, 40072, 40073, 40074, 40075, 40076, 40077, 40078, 40079,\n    40080, 40081, 40082, 40083, 40084, 40085, 40086, 40087, 40088, 40089,\n    40090, 40091, 40092, 40093, 40094, 40095, 40096, 40097, 40098, 40099,\n    40100, 40101, 40102, 40103, 40104, 40105, 40106, 40107, 40108, 40109,\n    40110, 40111, 40112, 40113, 40114, 40115, 40116, 40117, 40118, 40119,\n    40120, 40121, 40122, 40123, 40124, 40125, 40126, 40127, 40128, 40129,\n    40130, 40131, 40132, 40133, 40134, 40135, 40136, 40137, 40138, 40139,\n    40140, 40141, 40142, 40143, 40144, 40145, 40146, 40147, 40148, 40149,\n    40150, 40151, 40152, 40153, 40154, 40155, 40156, 40157, 40158, 40159,\n    40160, 40161, 40162, 40163, 40164, 40165, 40166, 40167, 40168, 40169,\n    40170, 40171, 40172, 40173, 40174, 40175, 40176, 40177, 40178, 40179,\n    40180, 40181, 40182, 40183, 40184, 40185, 40186, 40187, 40188, 40189,\n    40190, 40191, 40192, 40193, 40194, 40195, 40196, 40197 ];\n\nconst values = [21365, 28243, 1, 65, 18034, 28526, 26997, 29440, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    21357, 24946, 29728, 19813, 29797, 29216, 21587, 8246, 13633, 11571, \n    0, 0, 0, 0, 0, 0, 15472, 29289, 28001, 29305,\n    15872, 0, 0, 0, 12590, 13056, 0, 0, 0, 0,\n    0, 0, 13111, 13111, 13111, 12851, 13360, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 204, 213,\n    124, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 65535, 0 ]\n\nconst reg1 = registers.map(reg => reg - 40000)\nconst reg2 = reg1.splice(100)\nconst values2 = values.splice(100)\n\nconst p1 = {\n    'value': values,\n    'fc': 16,\n    'unitid': 1,\n    'address': reg1,\n    'quantity': values.length\n}\nconst p2 = {\n    'value': values2,\n    'fc': 16,\n    'unitid': 1,\n    'address': reg2,\n    'quantity': values2.length\n}\n\nnode.send({payload: p1})\nnode.send({payload: p2})\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":2040,"y":200,"wires":[["eb56533ecf4f4f3c"]]},{"id":"f4e2a505c51b636e","type":"modbus-flex-getter","z":"eecddba75d36c6cd","name":"","showStatusActivities":false,"showErrors":false,"logIOActivities":false,"server":"5a03de1d4dae16b8","useIOFile":false,"ioFile":"","useIOForPayload":false,"emptyMsgOnFail":false,"keepMsgProperties":false,"x":2010,"y":320,"wires":[["c05ef2bcd9f15d19"],[]]},{"id":"2c0401832b4e68a9","type":"inject","z":"eecddba75d36c6cd","name":"get 40000:10","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{\"fc\":3,\"unitid\":1,\"address\":0,\"quantity\":10}","payloadType":"json","x":1810,"y":340,"wires":[["f4e2a505c51b636e"]]},{"id":"c05ef2bcd9f15d19","type":"function","z":"eecddba75d36c6cd","name":"compare first 10","func":"const expectedValues = [21365, 28243, 1, 65, 18034, 28526, 26997, 29440, 0, 0]\nconst data = msg.payload\nlet result = '✅ Data matches'\nif (Array.isArray(data) == false) {\n    result = `Data Read not an array`\n} else if (data.length != expectedValues.length) {\n    result = `Data Read Length is ${data.length}. Expected ${expectedValues.length}`\n} else {\n    for (let index = 0; index < data.length; index++) {\n        const expected = expectedValues[index];\n        const readData = data[index];\n        if (expected !== readData) {\n            result = `Data at register ${40000 + index} is ${readData}. Expected ${expected}`\n            break\n        }\n    }\n}\nmsg.payload = {\n    result: result,\n    readData: data,\n    expected: expectedValues\n}\nreturn msg\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":2240,"y":320,"wires":[["2d5e5b1b1f33b9fb"]]},{"id":"2d5e5b1b1f33b9fb","type":"debug","z":"eecddba75d36c6cd","name":"debug 192","active":true,"tosidebar":true,"console":false,"tostatus":true,"complete":"payload","targetType":"msg","statusVal":"payload","statusType":"auto","x":2250,"y":380,"wires":[]},{"id":"941ffc08d2760e77","type":"inject","z":"eecddba75d36c6cd","name":"","props":[],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":1790,"y":240,"wires":[["d1e725ef2283421f"]]},{"id":"d1e725ef2283421f","type":"function","z":"eecddba75d36c6cd","name":"Clear headers","func":"\nconst ninetyNineZeros = []\nninetyNineZeros.length = 99\nninetyNineZeros.fill(0)\n\nconst p1 = {\n    'value': ninetyNineZeros,\n    'fc': 16,\n    'unitid': 1,\n    'address': 0,\n    'quantity': ninetyNineZeros.length\n}\nconst p2 = {\n    'value': ninetyNineZeros,\n    'fc': 16,\n    'unitid': 1,\n    'address': 99,\n    'quantity': ninetyNineZeros.length\n}\n\nconst p3 = {\n    'value': ninetyNineZeros,\n    'fc': 16,\n    'unitid': 1,\n    'address': 40000,\n    'quantity': ninetyNineZeros.length\n}\nconst p4 = {\n    'value': ninetyNineZeros,\n    'fc': 16,\n    'unitid': 1,\n    'address': 40099,\n    'quantity': ninetyNineZeros.length\n}\n\nnode.send({payload: p1})\nnode.send({payload: p2})\nnode.send({payload: p3})\nnode.send({payload: p4})\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1980,"y":240,"wires":[["eb56533ecf4f4f3c"]]},{"id":"2b5c898486b75fc3","type":"modbus-server","z":"eecddba75d36c6cd","name":"","logEnabled":true,"hostname":"0.0.0.0","serverPort":"10512","responseDelay":100,"delayUnit":"ms","coilsBufferSize":10000,"holdingBufferSize":"41000","inputBufferSize":10000,"discreteBufferSize":10000,"showErrors":true,"x":2260,"y":100,"wires":[[],[],[],[],[]]},{"id":"7862a839aa58329c","type":"function","z":"eecddba75d36c6cd","name":"Write Headers to 4400000 (quicker)","func":"const registers = [40000, 40001, 40002, 40003, 40004, 40005, 40006, 40007, 40008, 40009,\n    40010, 40011, 40012, 40013, 40014, 40015, 40016, 40017, 40018, 40019,\n    40020, 40021, 40022, 40023, 40024, 40025, 40026, 40027, 40028, 40029,\n    40030, 40031, 40032, 40033, 40034, 40035, 40036, 40037, 40038, 40039,\n    40040, 40041, 40042, 40043, 40044, 40045, 40046, 40047, 40048, 40049,\n    40050, 40051, 40052, 40053, 40054, 40055, 40056, 40057, 40058, 40059,\n    40060, 40061, 40062, 40063, 40064, 40065, 40066, 40067, 40068, 40069,\n    40070, 40071, 40072, 40073, 40074, 40075, 40076, 40077, 40078, 40079,\n    40080, 40081, 40082, 40083, 40084, 40085, 40086, 40087, 40088, 40089,\n    40090, 40091, 40092, 40093, 40094, 40095, 40096, 40097, 40098, 40099,\n    40100, 40101, 40102, 40103, 40104, 40105, 40106, 40107, 40108, 40109,\n    40110, 40111, 40112, 40113, 40114, 40115, 40116, 40117, 40118, 40119,\n    40120, 40121, 40122, 40123, 40124, 40125, 40126, 40127, 40128, 40129,\n    40130, 40131, 40132, 40133, 40134, 40135, 40136, 40137, 40138, 40139,\n    40140, 40141, 40142, 40143, 40144, 40145, 40146, 40147, 40148, 40149,\n    40150, 40151, 40152, 40153, 40154, 40155, 40156, 40157, 40158, 40159,\n    40160, 40161, 40162, 40163, 40164, 40165, 40166, 40167, 40168, 40169,\n    40170, 40171, 40172, 40173, 40174, 40175, 40176, 40177, 40178, 40179,\n    40180, 40181, 40182, 40183, 40184, 40185, 40186, 40187, 40188, 40189,\n    40190, 40191, 40192, 40193, 40194, 40195, 40196, 40197 ];\n\nconst values = [21365, 28243, 1, 65, 18034, 28526, 26997, 29440, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    21357, 24946, 29728, 19813, 29797, 29216, 21587, 8246, 13633, 11571, \n    0, 0, 0, 0, 0, 0, 15472, 29289, 28001, 29305,\n    15872, 0, 0, 0, 12590, 13056, 0, 0, 0, 0,\n    0, 0, 13111, 13111, 13111, 12851, 13360, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 204, 213,\n    124, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 65535, 0 ]\n\nconst reg1 = registers.map(reg => reg)\nconst reg2 = reg1.splice(100)\nconst values2 = values.splice(100)\n\nconst p1 = {\n    'value': values,\n    'fc': 16,\n    'unitid': 1,\n    'address': reg1,\n    'quantity': values.length\n}\nconst p2 = {\n    'value': values2,\n    'fc': 16,\n    'unitid': 1,\n    'address': reg2,\n    'quantity': values2.length\n}\n\nnode.send({payload: p1})\nnode.send({payload: p2})\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":2040,"y":160,"wires":[["eb56533ecf4f4f3c"]]},{"id":"c26bbd0680fae5f0","type":"inject","z":"eecddba75d36c6cd","name":"","props":[],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":1790,"y":160,"wires":[["7862a839aa58329c"]]},{"id":"e0092c2bcb4b851f","type":"inject","z":"eecddba75d36c6cd","name":"get 440000:10","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{\"fc\":3,\"unitid\":1,\"address\":40000,\"quantity\":10}","payloadType":"json","x":1810,"y":300,"wires":[["f4e2a505c51b636e"]]},{"id":"5a03de1d4dae16b8","type":"modbus-client","name":"myServer 10512","clienttype":"tcp","bufferCommands":true,"stateLogEnabled":false,"queueLogEnabled":false,"failureLogEnabled":true,"tcpHost":"127.0.0.1","tcpPort":"10512","tcpType":"DEFAULT","serialPort":"/dev/ttyUSB","serialType":"RTU-BUFFERD","serialBaudrate":"9600","serialDatabits":"8","serialStopbits":"1","serialParity":"none","serialConnectionDelay":"100","serialAsciiResponseStartDelimiter":"0x3A","unit_id":"1","commandDelay":"1","clientTimeout":"1000","reconnectOnTimeout":true,"reconnectTimeout":"2000","parallelUnitIdsAllowed":true}]

Hope that helps.

thank you steve! this one helped, it works. :slight_smile:

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.