Hi @jamhacker
Welcome to openHAB.
- does this work even if openHAB is running on a Raspberry?
Iâm running it myself on an Raspberry Pi 3.
Please be aware that this is not a very nice solution due to the polling of many SPS variables for every cycle (a second or so), what generates huge traffic and overhead, as already criticized by @Hoode63 and @stm.
Another limitation is also the capability of the Pi for all the XPATH parsing needed for my solution.
But it works well for me with around 160 PLC variables and a cycle time of 1 second. I have it running since 8 months without any issues and itâs stable. Iâm using it daily in my productive system and Iâm satisfied with it for the moment.
As long as there is no MQTT support for TwinCat2 and no better openHAB binding possibility around, I definitely go with this.
For me, this is the solution with as less pain as possible for the moment. Without any third party technology or server. Just Beckhoffâs CX with the already there OPC server and the Pi with openHAB. All the complexity is programmatically expressed in a handful of openHAB rule files, that can be easily expanded and managed.
- Are all my sps variables available when the server is running or do I have to create or share them specifically?
All PLC variables should be available for the OPC server without doing something special.
On my CX there was everithing allready there and running. I did not have to change anything on the CX.
- sendHttpPostRequest: create or install something for this ?
This is just an ordinary openHAB command, that can be used in rules and allows to send a http post request. Actions | openHAB
- rule? do I create a separate file for each varianble in the folder rule? with name cX_Light_Sunblind_read like you?
I have one rule for all variables that will be read in the same cycle. For more variables, just add them to the content string of the post request and the xpath parsing as shown in my excample.
Iâhave created a second rule for variables with another, slower cycle. For example variables for room temperature or a weather station, where a cycle of 5 minutes is far enough to poll.
- âAL_Entre_Treppenhaus_Licht_EG.postUpdateâ is the counterpart on openhab site? where or how do I use that?
AL_Entre_Treppenhaus_Licht_EG is just an ordinary openHAB switch item.
Here is how i defined that in an .items file:
Switch AL_Entre_Treppenhaus_Licht_EG "Treppenhaus EG" <light> (AL_Entre_Treppenhaus) {autoupdate="false"}
Did I understand correctly that the rule files will go through every second automatically without further call and the values ââare written in the openhab variables?
The rules file from my example executes every second. The cycle time can be adjusted with the crone command.
- how can I use this variable? that would have to be a Chanel or item so that I can hang it graphically on an item?
I have no channels or bindings defined for my Beckhoff variables. Just items.
And I have installed and use the openHAB XPath, Scale and Map transformations.
The postUpdate command updates the item state if it has changed in the XPathâed xml stream from the plcâs service. The rules do all the job that channels and bindings would do.
I have managed another rule to write the values to the plc.
It listens to changes of the items from the openHab side and passes an equivalent OPC call to the plc.
Here an example:
rule "<CX_Schreiben>"
when
Item AL_Entre_Treppenhaus_Licht_EG received command or
Item AL_Entre_Treppenhaus_Licht_OG received command or
Item EG_KuecheEssen_Storre_Kueche received command or
Item EG_KuecheEssen_Storre_Essen received
then
var String url = "http://<yoursCxIpAddress>/TcPlcDataServiceDa.dll"
var String contentType = "text/xml"
var String contentWriteBeginning = '<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><Write xmlns="http://opcfoundation.org/webservices/XMLDA/1.0/"><Options ClientRequestHandle="1" /><ItemList>'
var String contentWriteEnd = '</ItemList></Write></soap:Body></soap:Envelope>'
var String content
if (triggeringItem.name == AL_Entre_Treppenhaus_Licht_EG.name)
{
if (AL_Entre_Treppenhaus_Licht_EG.state == OFF)
{
content = '<Items ItemName="PLC1.arrLightingCommands[1].bStart"><Value xsi:type="xsd:boolean">true</Value></Items>'
}
else
{
content = '<Items ItemName="PLC1.arrLightingCommands[1].bOff"><Value xsi:type="xsd:boolean">true</Value></Items>'
}
sendHttpPostRequest(url, contentType, contentWriteBeginning + content + contentWriteEnd)
}
if (triggeringItem.name == AL_Entre_Treppenhaus_Licht_OG.name)
{
if (AL_Entre_Treppenhaus_Licht_OG.state == OFF)
{
content = '<Items ItemName="PLC1.arrLightingCommands[2].bStart"><Value xsi:type="xsd:boolean">true</Value></Items>'
}
else
{
content = '<Items ItemName="PLC1.arrLightingCommands[2].bOff"><Value xsi:type="xsd:boolean">true</Value></Items>'
}
sendHttpPostRequest(url, contentType, contentWriteBeginning + content + contentWriteEnd)
}
if (triggeringItem.name == EG_KuecheEssen_Storre_Kueche.name)
{
if (receivedCommand.toString == 'DOWN')
{
content = '<Items ItemName="PLC1.arrSunblindCommands[1].bDown"><Value xsi:type="xsd:boolean">true</Value></Items>'
sendHttpPostRequest(url, contentType, contentWriteBeginning + content + contentWriteEnd)
}
if (receivedCommand.toString == 'STOP')
{
content = '<Items ItemName="PLC1.arrSunblindCommands[1].bStop"><Value xsi:type="xsd:boolean">true</Value></Items>'
sendHttpPostRequest(url, contentType, contentWriteBeginning + content + contentWriteEnd)
}
if (receivedCommand.toString == 'UP')
{
content = '<Items ItemName="PLC1.arrSunblindCommands[1].bUp"><Value xsi:type="xsd:boolean">true</Value></Items>'
sendHttpPostRequest(url, contentType, contentWriteBeginning + content + contentWriteEnd)
}
}
if (triggeringItem.name == EG_KuecheEssen_Storre_Essen.name)
{
if (receivedCommand.toString == 'DOWN')
{
content = '<Items ItemName="PLC1.arrSunblindCommands[2].bDown"><Value xsi:type="xsd:boolean">true</Value></Items>'
sendHttpPostRequest(url, contentType, contentWriteBeginning + content + contentWriteEnd)
}
if (receivedCommand.toString == 'STOP')
{
content = '<Items ItemName="PLC1.arrSunblindCommands[2].bStop"><Value xsi:type="xsd:boolean">true</Value></Items>'
sendHttpPostRequest(url, contentType, contentWriteBeginning + content + contentWriteEnd)
}
if (receivedCommand.toString == 'UP')
{
content = '<Items ItemName="PLC1.arrSunblindCommands[2].bUp"><Value xsi:type="xsd:boolean">true</Value></Items>'
sendHttpPostRequest(url, contentType, contentWriteBeginning + content + contentWriteEnd)
}
}
end