Home Automation Full Simulation Using TwidoSuite, OpenHAB and TeslaSCADA

Hello,
I’m Randi and I’m new to OpenHAB. I need help with my project.

I’m trying to make a Home Automation Full Simulation using some program as I mentioned above. I’m using modbus binding from @ssalonen in Modbus openHAB2 binding available for alpha testing. PLC that I will be using is modicon M221.

Here is my TwidoSuite Program Report :
doc2.pdf (1019.3 KB)

Here for the openHAB stuff :

modtest.things

Bridge modbus:tcp:localhostTCP [ host="192.168.0.105", port=502, id=1 ]{

    Bridge poller coils [ start=0, length=2, refresh=1000, type="coil" ]
		{
        Thing data internalrelay [ readStart="0", readValueType="uint16" ]
		Thing data light1on [ readStart="1", readValueType="bit" ]
		}
	Bridge poller coils [start=2, length=1, refresh=1000, type="coil" ]
		{
		Thing data terminalroom1on [ readStart="2", readValueType="bit", writeStart="2", writeValueType="bit", writeType="coil" ]
		}
    Bridge poller coils [start=3, length=2, refresh=1000, type="coil" ]
		{
		Thing data bathroom1on [ readStart="3", readValueType="bit" ]
		Thing data light2on [ readStart="4", readValueType="bit" ]
		}
	Bridge poller coils [start=5, length=1, refresh=1000, type="coil" ]
		{
		Thing data terminalroom2on [ readStart="5", readValueType="bit", writeStart="5", writeValueType="bit", writeType="coil" ]
		}
	Bridge poller coils [start=6, length=2, refresh=1000, type="coil" ]
		{
		Thing data bathroom2on [ readStart="6", readValueType="bit" ]
		Thing data light3on [ readStart="7", readValueType="bit" ]
		}
	Bridge poller coils [start=8, length=1, refresh=1000, type="coil" ]
		{
		Thing data terminalroom3on [ readStart="8", readValueType="bit", writeStart="8", writeValueType="bit", writeType="coil" ]
		}
	Bridge poller coils [start=9, length=1, refresh=1000, type="coil" ]
		{
		Thing data bathroom3on [ readStart="9", readValueType="bit" ]
		}

    Bridge poller holding [ start=0000, length=1, refresh=1000, type="holding" ]
		{
        Thing data uilight1 [ readStart="0000", readValueType="uint16", writeStart="0000", writeValueType="uint16", writeType="holding" ]
		}
	Bridge poller holding [ start=0002, length=1, refresh=1000, type="holding" ]
		{
        Thing data uibathroom1 [ readStart="0002", readValueType="uint16", writeStart="0002", writeValueType="uint16", writeType="holding" ]
		}
	Bridge poller holding [ start=0004, length=1, refresh=1000, type="holding" ]
		{
        Thing data uilight2 [ readStart="0004", readValueType="uint16", writeStart="0004", writeValueType="uint16", writeType="holding" ]
		}
	Bridge poller holding [ start=0006, length=1, refresh=1000, type="holding" ]
		{
        Thing data uibathroom2 [ readStart="0006", readValueType="uint16", writeStart="0006", writeValueType="uint16", writeType="holding" ]
		}
	Bridge poller holding [ start=0008, length=1, refresh=1000, type="holding" ]
		{
        Thing data uilight3 [ readStart="0008", readValueType="uint16", writeStart="0008", writeValueType="uint16", writeType="holding" ]
		}
	Bridge poller holding [ start=0010, length=1, refresh=1000, type="holding" ]
		{
        Thing data uibathroom3 [ readStart="0010", readValueType="uint16", writeStart="0010", writeValueType="uint16", writeType="holding" ]
		}
  
    Bridge poller holding [ start=0000, length=1, refresh=1000, type="holding" ]
		{   
        Thing data uilight1lo [ readStart="0000.0", readValueType="uint8" ]
        Thing data uilight1hi [ readStart="0000.1", readValueType="uint8" ]
		} 
	Bridge poller holding [ start=0002, length=1, refresh=1000, type="holding" ]
		{   
        Thing data uibathroom1lo [ readStart="0002.0", readValueType="uint8" ]
        Thing data uibathroom1hi [ readStart="0002.1", readValueType="uint8" ]
		}
	Bridge poller holding [ start=0004, length=1, refresh=1000, type="holding" ]
		{   
        Thing data uilight2lo [ readStart="0004.0", readValueType="uint8" ]
        Thing data uilight2hi [ readStart="0004.1", readValueType="uint8" ]
		}
	Bridge poller holding [ start=0006, length=1, refresh=1000, type="holding" ]
		{   
        Thing data uibathroom2lo [ readStart="0006.0", readValueType="uint8" ]
        Thing data uibathroom2hi [ readStart="0006.1", readValueType="uint8" ]
		}
	Bridge poller holding [ start=0008, length=1, refresh=1000, type="holding" ]
		{   
        Thing data uilight3lo [ readStart="0008.0", readValueType="uint8" ]
        Thing data uilight3hi [ readStart="0008.1", readValueType="uint8" ]
		}
	Bridge poller holding [ start=0010, length=1, refresh=1000, type="holding" ]
		{   
        Thing data uibathroom3lo [ readStart="0010.0", readValueType="uint8" ]
        Thing data uibathroom3hi [ readStart="0010.1", readValueType="uint8" ]
		}
}

modtest.items

Group Room1
Group Room2
Group Room3

Switch internalrelay			  "Internal Relay [%d]"		<energy> { channel="modbus:data:localhostTCP:coils:internalrelay:switch" }
Switch terminalroom1on            "Terminal Room 1 [%d]"    (Room1) { channel="modbus:data:localhostTCP:coils:terminalroom1on:switch" }
Switch terminalroom2on            "Terminal Room 2 [%d]"    (Room2) { channel="modbus:data:localhostTCP:coils:terminalroom2on:switch" }
Switch terminalroom3on			  "Terminal Room 3 [%d]"	(Room3) { channel="modbus:data:localhostTCP:coils:terminalroom3on:switch" }
 
Switch uilight1            "Light Room 1 [%d]"    		<light> (Room1) { channel="modbus:data:localhostTCP:holding:uilight1:switch" }
Switch uibathroom1		   "Light Bathroom 1 [%d]"    	<bath> (Room1) { channel="modbus:data:localhostTCP:holding:uibathroom1:switch" }
Switch uilight2            "Light Room 2 [%d]"    		<light> (Room2) { channel="modbus:data:localhostTCP:holding:uilight2:switch" }
Switch uibathroom2		   "Light Bathroom 2[%d]"		<bath> (Room2) { channel="modbus:data:localhostTCP:holding:uibathroom2:switch" }
Switch uilight3			   "Light Room 3 [%d]"			<light> (Room3) { channel="modbus:data:localhostTCP:holding:uilight3:switch" }
Switch uibathroom3		   "Light Bathroom 3 [%d]"		<bath> (Room3) { channel="modbus:data:localhostTCP:holding:uibathroom3:switch" }

modtest.sitemap

sitemap modtest label="modtest"
{
    Frame {
		Switch item=internalrelay
        Group item=Room1 label="Room 1" icon="bedroom"
		Group item=Room2 label="Room 2" icon="bedroom"
		Group item=Room3 label="Room 3" icon="bedroom"
		} 
}

Here for TeslaScada UI (sorry I can’t attach my TeslaScada files bcs it’s not supported :frowning:) :

Screenshot

home%20ss

every room will be like this
room%20ss

In this project, OpenHAB will act as Interface for the Cloud Control and TeslaScada as the Manual Switch Interface to replace the house miniature.

There is some question I want ask :

  1. About my addressing for coils and holding register in the things coding, is there any mistake ?
  2. Can anybody give me some clue about configuration in the modbus.cfg ? I don’t really get about that :frowning:
  3. Is there another bindings I should use for this project ?

Sorry for my bad english and grammar. I hope you can understand what I mean :sweat_smile:
Thank you so much

Hi!
Same thing formatted a bit differently, it was hard for me to read it with the indentation

Bridge modbus:tcp:localhostTCP [ host="192.168.0.105", port=502, id=1 ]{
    Bridge poller coils [ start=0, length=2, refresh=1000, type="coil" ] {
        Thing data internalrelay [ readStart="0", readValueType="uint16" ]
        Thing data light1on [ readStart="1", readValueType="bit" ]
    }
    Bridge poller coils [start=2, length=1, refresh=1000, type="coil" ] {
        Thing data terminalroom1on [ readStart="2", readValueType="bit", writeStart="2", writeValueType="bit", writeType="coil" ]
    }
    Bridge poller coils [start=3, length=2, refresh=1000, type="coil" ] {
        Thing data bathroom1on [ readStart="3", readValueType="bit" ]
        Thing data light2on [ readStart="4", readValueType="bit" ]
    }
    Bridge poller coils [start=5, length=1, refresh=1000, type="coil" ] {
        Thing data terminalroom2on [ readStart="5", readValueType="bit", writeStart="5", writeValueType="bit", writeType="coil" ]
    }
    Bridge poller coils [start=6, length=2, refresh=1000, type="coil" ] {
        Thing data bathroom2on [ readStart="6", readValueType="bit" ]
        Thing data light3on [ readStart="7", readValueType="bit" ]
    }
    Bridge poller coils [start=8, length=1, refresh=1000, type="coil" ] {
        Thing data terminalroom3on [ readStart="8", readValueType="bit", writeStart="8", writeValueType="bit", writeType="coil" ]
    }
    Bridge poller coils [start=9, length=1, refresh=1000, type="coil" ] {
        Thing data bathroom3on [ readStart="9", readValueType="bit" ]
    }
    Bridge poller holding [ start=0000, length=1, refresh=1000, type="holding" ] {
        Thing data uilight1 [ readStart="0000", readValueType="uint16", writeStart="0000", writeValueType="uint16", writeType="holding" ]
    }
    Bridge poller holding [ start=0002, length=1, refresh=1000, type="holding" ] {
        Thing data uibathroom1 [ readStart="0002", readValueType="uint16", writeStart="0002", writeValueType="uint16", writeType="holding" ]
    }
    Bridge poller holding [ start=0004, length=1, refresh=1000, type="holding" ] {
        Thing data uilight2 [ readStart="0004", readValueType="uint16", writeStart="0004", writeValueType="uint16", writeType="holding" ]
    }
    Bridge poller holding [ start=0006, length=1, refresh=1000, type="holding" ] {
        Thing data uibathroom2 [ readStart="0006", readValueType="uint16", writeStart="0006", writeValueType="uint16", writeType="holding" ]
    }
    Bridge poller holding [ start=0008, length=1, refresh=1000, type="holding" ] {
        Thing data uilight3 [ readStart="0008", readValueType="uint16", writeStart="0008", writeValueType="uint16", writeType="holding" ]
    }
    Bridge poller holding [ start=0010, length=1, refresh=1000, type="holding" ] {
        Thing data uibathroom3 [ readStart="0010", readValueType="uint16", writeStart="0010", writeValueType="uint16", writeType="holding" ]
    }
    Bridge poller holding [ start=0000, length=1, refresh=1000, type="holding" ] {
        Thing data uilight1lo [ readStart="0000.0", readValueType="uint8" ]
        Thing data uilight1hi [ readStart="0000.1", readValueType="uint8" ]
    } 
    Bridge poller holding [ start=0002, length=1, refresh=1000, type="holding" ] {
        Thing data uibathroom1lo [ readStart="0002.0", readValueType="uint8" ]
        Thing data uibathroom1hi [ readStart="0002.1", readValueType="uint8" ]
    }
    Bridge poller holding [ start=0004, length=1, refresh=1000, type="holding" ] {
        Thing data uilight2lo [ readStart="0004.0", readValueType="uint8" ]
        Thing data uilight2hi [ readStart="0004.1", readValueType="uint8" ]
    }
    Bridge poller holding [ start=0006, length=1, refresh=1000, type="holding" ] {
        Thing data uibathroom2lo [ readStart="0006.0", readValueType="uint8" ]
        Thing data uibathroom2hi [ readStart="0006.1", readValueType="uint8" ]
    }
    Bridge poller holding [ start=0008, length=1, refresh=1000, type="holding" ] {
        Thing data uilight3lo [ readStart="0008.0", readValueType="uint8" ]
        Thing data uilight3hi [ readStart="0008.1", readValueType="uint8" ]
    }
    Bridge poller holding [ start=0010, length=1, refresh=1000, type="holding" ] {
        Thing data uibathroom3lo [ readStart="0010.0", readValueType="uint8" ]
        Thing data uibathroom3hi [ readStart="0010.1", readValueType="uint8" ]
    }
}

There are quite many small things a bit off there, but the genral idea looks good I think.

  • Why so many pollers? Why not read all relevant coils/holding registers at once? E.g. with start=0 and length=10. With some devices it is necessary to read the data “in pieces”, similar what you are now doing. However, many devices do accept reading the necessary data all at once, especially if it contiguous piece of data (like you have?)
  • openHAB does not allow same thing names. You now have many poller things named coils. Same comment applies to holding
  • readValueType with coils must be bit, not uint16. What would it even mean? I think you you would get configuration error with the current config.
  • there are some “weird” data thing readStart values, e.g. readStart="0000". Might work, or might not. If it doesn’t you should at least get clear error. I suggest you follow the format set in examples in docs
  • there are some “weird” poller thing start values, e.g. start=0004. Might work, or might not – haven’t really tried it out. I suggest you follow the format set in examples in docs. In some languages, it is not valid to have zeroes before the integer.

Regarding modbus.cfg. I hope you understand the documentation in docs.openhab.org refer to modbus binding version 1. You are presumably using modbus binding version 2 – find the docs from github. Please note that there is no modbus.cfg for version 2.

Also can’t comment about other bindings, not too familiar with all the alternatives with your device. I do have a bit similar use case with my Siemens PLC, using modbus binding there.

Best,
Sami

Thank you @ssalonen for your reply.

  • I’m actually confused about the addressing for the holding registers. In https://github.com/ssalonen/openhab2-addons/blob/modbus-openhab2-native-binding/addons/binding/org.openhab.binding.modbus/README.md, the holding registers values start from 1501 for 401501 addressing. In my case I’m using the first holding register with value 400000. I think “maybe” I should use 0000 for that value :sweat_smile: That’s why I’m using a lot of 000x value for the holding register. Or maybe I can use address 1 for the first holding registers and so on ?

  • About the pollers in the coil, can I have a different task for read and write in the same pollers ? bcs some coils in my project do read and write, and some of it only read. I’m making a lot of pollers because I’m not sure if I can do different task in one pollers.

  • About pollers for holding register, I will try to make it to one pollers since it’s the same read and write task.

  • In your case, are using “add-on” to your PLC ? bcs I’m only using the Modicon M221

Thank you for your answer. It does help a lot :smile:

Hmm the addressing is indeed confusing in modbus world, different sources use different terminology.

Best source for the binding is the “Comment on adressing” in the docs. Take note on the distinction between “entity numbers” and “entity addresses”.

About the pollers in the coil, can I have a different task for read and write in the same pollers ? bcs some coils in my project do read and write, and some of it only read. I’m making a lot of pollers because I’m not sure if I can do different task in one pollers.

Pollers are things responsible of just…polling the data – no writing.

When you sendCommand to an item bound to a data thing channel, write action will be performed in the modbus binding. Which kind of write? Depends on writeType, writeStart etc. You can also have read-only data things, or write-only data things. Docs should have examples of both.

You can indeed mix and match read/write types, e.g. read from discrete inputs, but write to coils (see Writing to different address and type than read). This means that openHAB item state is reflecting the status of modbus slave discrete input and received openHAB commands are transformed to modbus coil write requests.

About pollers for holding register, I will try to make it to one pollers since it’s the same read and write task.

Not sure I get your point… see discussion above.

Hope this helps!

Sami

Thank you very much for your help, sir. Tomorrow I’m going to try and run this project with all the programs that I’ll be using. I will update this thread soon!

Thank you very much :smile:

1 Like

Sorry for the very late reply. I’m finally get to try openHAB and PLC today because there was training using the PLC that I need. So this is the result that I get.

I’m using 4 software to test it:

  1. Somachine Basic (I’m using this because TwidoSuite cannot simulate the Ladder Diagram virtually, so I can’t do the full simulation test)
  2. Poll modbus (To write directly to PLC memory)
  3. Tesla SCADA
  4. OpenHAB

I’m using TP-Link Pocket Router so I can connect the PLC to both phone and laptop at the same time. (Local Connection, without internet connection. TP-Link act as Local Router)
The purpose of connecting to the PLC is to test the memory access to the PLC from other software.

First, when Poll Modbus connect directly to the PLC through TP-Link, it works fine, connection running.
And then, I run openHAB from my laptop and Poll Modbus from my phone at the same time. When I try to write to any coils, openHAB not responding to the coil state change. Then I try to change the connection host, bcs I thought the connection host parameter isn’t right, and I change my laptop IP address as well both to static and dynamic. But openHAB still not responding to any change. Did I have to use online internet connection to run openHAB along with the PLC ?

here the coding that I use to test.

onsite.things

Bridge modbus:tcp:localhostTCP [ host="192.168.0.105", port=502, id=1 ]
{
    Bridge poller coils [ start=0, length=9, refresh=500, type="coil" ]
		{
        Thing data digital1 [ readStart="0", readValueType="bit", writeStart="0", writeValueType="bit", writeType="coil" ]
		Thing data digital2	[ readStart="1", readValueType="bit", writeStart="1", writeValueType="bit", writeType="coil" ]
		Thing data digital3	[ readStart="2", readValueType="bit", writeStart="2", writeValueType="bit", writeType="coil" ]
		Thing data digital4	[ readStart="3", readValueType="bit", writeStart="3", writeValueType="bit", writeType="coil" ]
		Thing data digital5	[ readStart="4", readValueType="bit", writeStart="4", writeValueType="bit", writeType="coil" ]
		Thing data digital6	[ readStart="5", readValueType="bit", writeStart="5", writeValueType="bit", writeType="coil" ]
		Thing data digital7	[ readStart="6", readValueType="bit", writeStart="6", writeValueType="bit", writeType="coil" ]
		Thing data digital8	[ readStart="7", readValueType="bit", writeStart="7", writeValueType="bit", writeType="coil" ]
		Thing data digital9	[ readStart="8", readValueType="bit", writeStart="8", writeValueType="bit", writeType="coil" ]
		}
		
		Bridge poller coils [ start=0, length=9, refresh=500, type="holding" ]
		{
        Thing data analog1 	[ readStart="0", readValueType="float32", writeStart="0", writeValueType="float32", writeType="holding" ]
		Thing data analog2	[ readStart="1", readValueType="float32", writeStart="1", writeValueType="float32", writeType="holding" ]
		Thing data analog3	[ readStart="2", readValueType="float32", writeStart="2", writeValueType="float32", writeType="holding" ]
		Thing data analog4	[ readStart="3", readValueType="float32", writeStart="3", writeValueType="float32", writeType="holding" ]
		Thing data analog5	[ readStart="4", readValueType="float32", writeStart="4", writeValueType="float32", writeType="holding" ]
		Thing data analog6	[ readStart="5", readValueType="float32", writeStart="5", writeValueType="float32", writeType="holding" ]
		Thing data analog7	[ readStart="6", readValueType="float32", writeStart="6", writeValueType="float32", writeType="holding" ]
		Thing data analog8	[ readStart="7", readValueType="float32", writeStart="7", writeValueType="float32", writeType="holding" ]
		Thing data analog9	[ readStart="8", readValueType="float32", writeStart="8", writeValueType="float32", writeType="holding" ]
		}
		}

onsite.items

Switch digital1		   		  "Digital 1 [%d]"			{ channel="modbus:data:localhostTCP:coils:digital1:switch" }
Switch digital2		   		  "Digital 2 [%d]"			{ channel="modbus:data:localhostTCP:coils:digital2:switch" }
Switch digital3		   		  "Digital 3 [%d]"			{ channel="modbus:data:localhostTCP:coils:digital3:switch" }
Switch digital4		   		  "Digital 4 [%d]"			{ channel="modbus:data:localhostTCP:coils:digital4:switch" }
Switch digital5		   		  "Digital 5 [%d]"			{ channel="modbus:data:localhostTCP:coils:digital5:switch" }
Switch digital6		   		  "Digital 6 [%d]"			{ channel="modbus:data:localhostTCP:coils:digital6:switch" }
Switch digital7		   		  "Digital 7 [%d]"			{ channel="modbus:data:localhostTCP:coils:digital7:switch" }
Switch digital8		   		  "Digital 8 [%d]"			{ channel="modbus:data:localhostTCP:coils:digital8:switch" }
Switch digital9		   		  "Digital 9 [%d]"			{ channel="modbus:data:localhostTCP:coils:digital9:switch" }

Number analog1				  "Analog 1 [%.1f]"			{channel="modbus:data:localhostTCP:holding:analog1:number" }
Number analog2				  "Analog 2 [%.1f]"			{channel="modbus:data:localhostTCP:holding:analog2:number" }
Number analog3				  "Analog 3 [%.1f]"			{channel="modbus:data:localhostTCP:holding:analog3:number" }
Number analog4				  "Analog 4 [%.1f]"			{channel="modbus:data:localhostTCP:holding:analog4:number" }
Number analog5				  "Analog 5 [%.1f]"			{channel="modbus:data:localhostTCP:holding:analog5:number" }
Number analog6				  "Analog 6 [%.1f]"			{channel="modbus:data:localhostTCP:holding:analog6:number" }
Number analog7				  "Analog 7 [%.1f]"			{channel="modbus:data:localhostTCP:holding:analog7:number" }
Number analog8				  "Analog 8 [%.1f]"			{channel="modbus:data:localhostTCP:holding:analog8:number" }
Number analog9				  "Analog 9 [%.1f]"			{channel="modbus:data:localhostTCP:holding:analog9:number" }

onsite.sitemap

sitemap onsite label="onsite"
{
    Frame {
		Switch item=digital1 label="Digital 1"
		Switch item=digital2 label="Digital 2"
		Switch item=digital3 label="Digital 3"
		Switch item=digital4 label="Digital 4"
		Switch item=digital5 label="Digital 5"
		Switch item=digital6 label="Digital 6"
		Switch item=digital7 label="Digital 7"
		Switch item=digital8 label="Digital 8"
		Switch item=digital9 label="Digital 9"
        
		Default item=analog1 label="Analog 1"
		Default item=analog2 label="Analog 2"
		Default item=analog3 label="Analog 3"
		Default item=analog4 label="Analog 4"
		Default item=analog5 label="Analog 5"
		Default item=analog6 label="Analog 6"
		Default item=analog7 label="Analog 7"
		Default item=analog8 label="Analog 8"
		Default item=analog9 label="Analog 9"
		} 
}

Does anyone knows how to fix this ?

Thanks,

Randi