├── .gitignore ├── .project ├── .settings ├── org.eclipse.jdt.core.prefs └── org.eclipse.m2e.core.prefs ├── LICENCE ├── README.md ├── pom.xml └── src ├── assembly ├── jar.xml ├── pack.xml └── runtime.xml └── main ├── java └── de │ └── myandres │ └── optolink │ ├── BroadcastListner.java │ ├── Channel.java │ ├── Config.java │ ├── Main.java │ ├── OptolinkInterface.java │ ├── SocketHandler.java │ ├── Telegram.java │ ├── Thing.java │ ├── Viessmann300.java │ ├── ViessmannHandler.java │ ├── ViessmannKW.java │ └── ViessmannProtocol.java └── resources ├── INSTALL_AUTOSTART.txt ├── logback.xml ├── logback_debug.xml ├── logback_trace.xml ├── optolink-ob.xml ├── optolink.init.d ├── optolink.xml ├── start.sh ├── start_debug.sh ├── start_trace.sh └── stop.sh /.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | /.classpath 3 | conf/ 4 | logs/ 5 | .settings/ 6 | optolink.xml 7 | start.bat 8 | start.sh 9 | start_debug.sh 10 | things-types vs optolink - comparison.xlsx 11 | .gitignore 12 | -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | optolink 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | org.eclipse.m2e.core.maven2Builder 15 | 16 | 17 | 18 | 19 | 20 | org.eclipse.jdt.core.javanature 21 | org.eclipse.m2e.core.maven2Nature 22 | 23 | 24 | -------------------------------------------------------------------------------- /.settings/org.eclipse.jdt.core.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled 3 | org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate 4 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 5 | org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve 6 | org.eclipse.jdt.core.compiler.compliance=1.8 7 | org.eclipse.jdt.core.compiler.debug.lineNumber=generate 8 | org.eclipse.jdt.core.compiler.debug.localVariable=generate 9 | org.eclipse.jdt.core.compiler.debug.sourceFile=generate 10 | org.eclipse.jdt.core.compiler.problem.assertIdentifier=error 11 | org.eclipse.jdt.core.compiler.problem.enumIdentifier=error 12 | org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning 13 | org.eclipse.jdt.core.compiler.source=1.8 14 | -------------------------------------------------------------------------------- /.settings/org.eclipse.m2e.core.prefs: -------------------------------------------------------------------------------- 1 | activeProfiles= 2 | eclipse.preferences.version=1 3 | resolveWorkspaceProjects=true 4 | version=1 5 | -------------------------------------------------------------------------------- /LICENCE: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | 9 | This version of the GNU Lesser General Public License incorporates 10 | the terms and conditions of version 3 of the GNU General Public 11 | License, supplemented by the additional permissions listed below. 12 | 13 | 0. Additional Definitions. 14 | 15 | As used herein, "this License" refers to version 3 of the GNU Lesser 16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 17 | General Public License. 18 | 19 | "The Library" refers to a covered work governed by this License, 20 | other than an Application or a Combined Work as defined below. 21 | 22 | An "Application" is any work that makes use of an interface provided 23 | by the Library, but which is not otherwise based on the Library. 24 | Defining a subclass of a class defined by the Library is deemed a mode 25 | of using an interface provided by the Library. 26 | 27 | A "Combined Work" is a work produced by combining or linking an 28 | Application with the Library. The particular version of the Library 29 | with which the Combined Work was made is also called the "Linked 30 | Version". 31 | 32 | The "Minimal Corresponding Source" for a Combined Work means the 33 | Corresponding Source for the Combined Work, excluding any source code 34 | for portions of the Combined Work that, considered in isolation, are 35 | based on the Application, and not on the Linked Version. 36 | 37 | The "Corresponding Application Code" for a Combined Work means the 38 | object code and/or source code for the Application, including any data 39 | and utility programs needed for reproducing the Combined Work from the 40 | Application, but excluding the System Libraries of the Combined Work. 41 | 42 | 1. Exception to Section 3 of the GNU GPL. 43 | 44 | You may convey a covered work under sections 3 and 4 of this License 45 | without being bound by section 3 of the GNU GPL. 46 | 47 | 2. Conveying Modified Versions. 48 | 49 | If you modify a copy of the Library, and, in your modifications, a 50 | facility refers to a function or data to be supplied by an Application 51 | that uses the facility (other than as an argument passed when the 52 | facility is invoked), then you may convey a copy of the modified 53 | version: 54 | 55 | a) under this License, provided that you make a good faith effort to 56 | ensure that, in the event an Application does not supply the 57 | function or data, the facility still operates, and performs 58 | whatever part of its purpose remains meaningful, or 59 | 60 | b) under the GNU GPL, with none of the additional permissions of 61 | this License applicable to that copy. 62 | 63 | 3. Object Code Incorporating Material from Library Header Files. 64 | 65 | The object code form of an Application may incorporate material from 66 | a header file that is part of the Library. You may convey such object 67 | code under terms of your choice, provided that, if the incorporated 68 | material is not limited to numerical parameters, data structure 69 | layouts and accessors, or small macros, inline functions and templates 70 | (ten or fewer lines in length), you do both of the following: 71 | 72 | a) Give prominent notice with each copy of the object code that the 73 | Library is used in it and that the Library and its use are 74 | covered by this License. 75 | 76 | b) Accompany the object code with a copy of the GNU GPL and this license 77 | document. 78 | 79 | 4. Combined Works. 80 | 81 | You may convey a Combined Work under terms of your choice that, 82 | taken together, effectively do not restrict modification of the 83 | portions of the Library contained in the Combined Work and reverse 84 | engineering for debugging such modifications, if you also do each of 85 | the following: 86 | 87 | a) Give prominent notice with each copy of the Combined Work that 88 | the Library is used in it and that the Library and its use are 89 | covered by this License. 90 | 91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 92 | document. 93 | 94 | c) For a Combined Work that displays copyright notices during 95 | execution, include the copyright notice for the Library among 96 | these notices, as well as a reference directing the user to the 97 | copies of the GNU GPL and this license document. 98 | 99 | d) Do one of the following: 100 | 101 | 0) Convey the Minimal Corresponding Source under the terms of this 102 | License, and the Corresponding Application Code in a form 103 | suitable for, and under terms that permit, the user to 104 | recombine or relink the Application with a modified version of 105 | the Linked Version to produce a modified Combined Work, in the 106 | manner specified by section 6 of the GNU GPL for conveying 107 | Corresponding Source. 108 | 109 | 1) Use a suitable shared library mechanism for linking with the 110 | Library. A suitable mechanism is one that (a) uses at run time 111 | a copy of the Library already present on the user's computer 112 | system, and (b) will operate properly with a modified version 113 | of the Library that is interface-compatible with the Linked 114 | Version. 115 | 116 | e) Provide Installation Information, but only if you would otherwise 117 | be required to provide such information under section 6 of the 118 | GNU GPL, and only to the extent that such information is 119 | necessary to install and execute a modified version of the 120 | Combined Work produced by recombining or relinking the 121 | Application with a modified version of the Linked Version. (If 122 | you use option 4d0, the Installation Information must accompany 123 | the Minimal Corresponding Source and Corresponding Application 124 | Code. If you use option 4d1, you must provide the Installation 125 | Information in the manner specified by section 6 of the GNU GPL 126 | for conveying Corresponding Source.) 127 | 128 | 5. Combined Libraries. 129 | 130 | You may place library facilities that are a work based on the 131 | Library side by side in a single library together with other library 132 | facilities that are not Applications and are not covered by this 133 | License, and convey such a combined library under terms of your 134 | choice, if you do both of the following: 135 | 136 | a) Accompany the combined library with a copy of the same work based 137 | on the Library, uncombined with any other library facilities, 138 | conveyed under the terms of this License. 139 | 140 | b) Give prominent notice with the combined library that part of it 141 | is a work based on the Library, and explaining where to find the 142 | accompanying uncombined form of the same work. 143 | 144 | 6. Revised Versions of the GNU Lesser General Public License. 145 | 146 | The Free Software Foundation may publish revised and/or new versions 147 | of the GNU Lesser General Public License from time to time. Such new 148 | versions will be similar in spirit to the present version, but may 149 | differ in detail to address new problems or concerns. 150 | 151 | Each version is given a distinguishing version number. If the 152 | Library as you received it specifies that a certain numbered version 153 | of the GNU Lesser General Public License "or any later version" 154 | applies to it, you have the option of following the terms and 155 | conditions either of that published version or of any later version 156 | published by the Free Software Foundation. If the Library as you 157 | received it does not specify a version number of the GNU Lesser 158 | General Public License, you may choose any version of the GNU Lesser 159 | General Public License ever published by the Free Software Foundation. 160 | 161 | If the Library as you received it specifies that a proxy can decide 162 | whether future versions of the GNU Lesser General Public License shall 163 | apply, that proxy's public statement of acceptance of any version is 164 | permanent authorization for you to choose that version for the 165 | Library. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # optolink 2 | 3 | Viessmann heating systems with vitotronic has a optolink Interface for maintenance. 4 | This interface can use for get/set data in the heating system. 5 | For more information about this interface see: http://openv.wikispaces.com/ 6 | 7 | The java-application is a slim adapter to this interface. 8 | On southbound it use the serial interface for connect the optolink interface (special hardware requert). 9 | On northbound it provides a TCP/IP raw Port for communication and a UDP/IP Port as broadcast interface 10 | to search the adapter in the local network. 11 | 12 | Primary is is develop for a adaption from [openhab2](https://github.com/openhab/openhab2/). 13 | It supports on the northbound the concept of openhab2 things. 14 | 15 | ##Build 16 | The application is develop in Eclipse (Luna) with maven support. 17 | Requierd Lib's: rxtx, slf4j, logback (see pom.xml file) 18 | You can build runtime by Run->Run As->Maven install. 19 | Files for runtime are found in ./traget 20 | Or download the install package from Github. 21 | 22 | ##Install & running 23 | All test was running on a Raspberry PI B with Raspbian "wheezy". 24 | Installing: 25 | 26 | 1. Install the rxtx (apt) 27 | 2. Config /dev/ttyAMA0 (see: https://cae2100.wordpress.com/2012/12/23/raspberry-pi-and-the-serial-port/) 28 | 3. Install your optolink hardware 29 | 4. copy: optolink-runtime.zip from the target folder to Rasberry and extract it. 30 | 5. Edit conf/optolink.xml for your heading system. 31 | 6. start it: ```./start_debug.sh ``` 32 | 33 | 34 | ##Test it 35 | Run a terminal programm (like putty), connect to you raspberry by using port 31113 and raw protocol. 36 | Suported command: 37 | 38 | * list -> list all (thing) definition (in xml-File) 39 | * get Thing.Id [channel.Id,channel.Id,..] -> get Data for thing from heating system. 40 | * set Thing-Id:Channel.Id value (The syntax of Value is not checked) 41 | 42 | ##Further doing (my ToDo List) 43 | 1. bug-fixing (if bugs found ;-) 44 | 2. Build a stable version (together with openhab2). 45 | 46 | 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | de.myandres.optolink 5 | optolink 6 | jar 7 | optolink 8 | 9 | 1.8 10 | 1.8 11 | 12 | 13 | 14 | 15 | maven-assembly-plugin 16 | 2.5.3 17 | 18 | 19 | jar-with-dependencies 20 | 21 | 22 | 23 | de.myandres.optolink.Main 24 | 25 | 26 | 27 | src/assembly/jar.xml 28 | src/assembly/pack.xml 29 | 30 | optolink 31 | 32 | 33 | 34 | make-assembly 35 | package 36 | 37 | single 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | org.slf4j 47 | slf4j-api 48 | 1.7.10 49 | 50 | 51 | 52 | ch.qos.logback 53 | logback-classic 54 | 1.1.2 55 | runtime 56 | 57 | 58 | org.rxtx 59 | rxtx 60 | 2.1.7 61 | 62 | 63 | 64 | 1.0.0-RC1 65 | -------------------------------------------------------------------------------- /src/assembly/jar.xml: -------------------------------------------------------------------------------- 1 | 4 | final 5 | 6 | jar 7 | 8 | false 9 | 10 | 11 | true 12 | runtime 13 | false 14 | 15 | 16 | 17 | 18 | ${project.build.outputDirectory} 19 | / 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /src/assembly/pack.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | bin 7 | 8 | tar.gz 9 | tar.bz2 10 | zip 11 | 12 | 13 | 14 | target 15 | lib 16 | 17 | *jar-with-dependencies.jar 18 | 19 | 20 | 21 | 22 | README* 23 | LICENCE 24 | 25 | unix 26 | 27 | 28 | 29 | src/main/resources 30 | conf 31 | 32 | *.xml 33 | 34 | unix 35 | 36 | 37 | src/main/resources 38 | 39 | 40 | *.sh 41 | *.txt 42 | 43 | unix 44 | 0755 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /src/assembly/runtime.xml: -------------------------------------------------------------------------------- 1 | 4 | runtime 5 | 6 | tar.gz 7 | tar.bz2 8 | zip 9 | 10 | 11 | 12 | target 13 | lib 14 | 15 | *jar-with-dependencies.jar 16 | 17 | 18 | 19 | 20 | README* 21 | LICENCE 22 | 23 | unix 24 | 25 | 26 | 27 | src/main/resources 28 | conf 29 | 30 | *.xml 31 | 32 | unix 33 | 34 | 35 | src/main/resources 36 | 37 | 38 | *.sh 39 | *.txt 40 | 41 | unix 42 | 0755 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /src/main/java/de/myandres/optolink/BroadcastListner.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2015, Stefan Andres. All rights reserved. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the GNU Lesser General Public License 6 | * (LGPL) version 3.0 which accompanies this distribution, and is available at 7 | * http://www.gnu.org/licenses/lgpl-3.0.html 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | *******************************************************************************/ 14 | package de.myandres.optolink; 15 | 16 | import java.net.DatagramPacket; 17 | import java.net.DatagramSocket; 18 | import java.net.InetAddress; 19 | import org.slf4j.Logger; 20 | import org.slf4j.LoggerFactory; 21 | 22 | public class BroadcastListner implements Runnable { 23 | 24 | static Logger log = LoggerFactory.getLogger(BroadcastListner.class); 25 | 26 | static final String BROADCAST_MESSAGE = "@@@@VITOTRONIC@@@@/"; 27 | int port; 28 | String connectedIP; 29 | String adapterID; 30 | 31 | 32 | 33 | BroadcastListner(int port, String adapterID) { 34 | log.debug("Init Broadcast Listener on Port", port); 35 | this.port = port; 36 | connectedIP = ""; 37 | this.adapterID =adapterID; 38 | } 39 | 40 | 41 | @Override 42 | public void run() { 43 | // Runs Listner 44 | log.debug("Listening for Broadcast...."); 45 | DatagramSocket datagramSocket = null; 46 | InetAddress remoteIPAddress; 47 | int remotePort; 48 | byte[] byteArray = new byte[1024]; 49 | 50 | try { 51 | datagramSocket = new DatagramSocket(port, InetAddress.getByName("0.0.0.0")); 52 | datagramSocket.setBroadcast(true); 53 | 54 | 55 | String str; 56 | 57 | while (true) { 58 | try { 59 | DatagramPacket resivedPacket = new DatagramPacket(byteArray , byteArray.length); 60 | datagramSocket.receive(resivedPacket); 61 | str = new String(resivedPacket.getData()).trim(); 62 | log.debug("Resived Broadcast Message: {}", str); 63 | remotePort = resivedPacket.getPort(); 64 | log.debug("From Port: {}", remotePort); 65 | remoteIPAddress = resivedPacket.getAddress(); 66 | log.debug("From Host: {}",remoteIPAddress.toString()); 67 | 68 | if (str.startsWith(BROADCAST_MESSAGE+adapterID) || 69 | str.startsWith(BROADCAST_MESSAGE+"*")) { 70 | // Someone calls me 71 | str = BROADCAST_MESSAGE + adapterID; 72 | byteArray = str.getBytes(); 73 | DatagramPacket sendPacket = new DatagramPacket(byteArray, 74 | byteArray.length, remoteIPAddress, remotePort); 75 | log.debug("Send: '{}' to {}:{}", str, remoteIPAddress.getHostAddress(), remotePort ); 76 | datagramSocket.send(sendPacket); 77 | 78 | 79 | } else { 80 | log.debug("Host: {}:{} calls with wrong message: {}", 81 | remoteIPAddress.getHostAddress(), 82 | remotePort, 83 | str); 84 | log.debug("Message will be ignor!"); 85 | } 86 | 87 | } catch (Exception e) { 88 | log.error("Something is wrong in broadcast listner thread!!! Diagnostic {}", e); 89 | log.error("Broadcast Listner die "); 90 | 91 | } } 92 | 93 | } catch (Exception e) { 94 | // TODO Auto-generated catch block 95 | log.error("Something is wrong in broadcast listner thread!!! Diagnostic {}", e); 96 | log.error("Broadcast Listner die"); 97 | 98 | } finally { 99 | try { 100 | if (datagramSocket != null) 101 | datagramSocket.close(); 102 | } catch (Exception e) { 103 | // Ignore 104 | } 105 | } 106 | } 107 | 108 | } 109 | -------------------------------------------------------------------------------- /src/main/java/de/myandres/optolink/Channel.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2015, Stefan Andres. All rights reserved. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the GNU Lesser General Public License 6 | * (LGPL) version 3.0 which accompanies this distribution, and is available at 7 | * http://www.gnu.org/licenses/lgpl-3.0.html 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | *******************************************************************************/ 14 | package de.myandres.optolink; 15 | 16 | import org.slf4j.Logger; 17 | import org.slf4j.LoggerFactory; 18 | 19 | public class Channel { 20 | 21 | static Logger logger = LoggerFactory.getLogger(Channel.class); 22 | 23 | 24 | private String id; 25 | private String description; 26 | private Telegram telegram; 27 | 28 | Channel (Channel channel) { 29 | logger.trace("Init id: '{}'", channel.getId() ); 30 | this.id = channel.getId(); 31 | this.description = channel.getDescription(); 32 | this.telegram = channel.getTelegram(); 33 | } 34 | 35 | Channel (String id ) { 36 | logger.trace("Init id: '{}'", id ); 37 | this.id = id; 38 | this.description = null; 39 | this.telegram = null; 40 | } 41 | 42 | 43 | public Telegram getTelegram() { 44 | return telegram; 45 | } 46 | 47 | public void setTelegram(Telegram telegram) { 48 | this.telegram = telegram; 49 | } 50 | 51 | public String getId() { 52 | return id; 53 | } 54 | public void setId(String id) { 55 | this.id = id; 56 | } 57 | 58 | public String getDescription() { 59 | return description; 60 | } 61 | 62 | public void setDescription(String description) { 63 | this.description = description; 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /src/main/java/de/myandres/optolink/Config.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2015, Stefan Andres. All rights reserved. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the GNU Lesser General Public License 6 | * (LGPL) version 3.0 which accompanies this distribution, and is available at 7 | * http://www.gnu.org/licenses/lgpl-3.0.html 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | *******************************************************************************/ 14 | package de.myandres.optolink; 15 | 16 | import java.io.FileReader; 17 | import java.util.ArrayList; 18 | import java.util.List; 19 | 20 | import org.xml.sax.Attributes; 21 | import org.xml.sax.ContentHandler; 22 | import org.xml.sax.InputSource; 23 | import org.xml.sax.Locator; 24 | import org.xml.sax.SAXException; 25 | import org.xml.sax.XMLReader; 26 | import org.xml.sax.helpers.XMLReaderFactory; 27 | import org.slf4j.Logger; 28 | import org.slf4j.LoggerFactory; 29 | 30 | /* 31 | * Contains Data from xml-File 32 | * This Data will be static only - dynamic data are stored in DataStore 33 | */ 34 | 35 | 36 | public class Config { 37 | 38 | static Logger log = LoggerFactory.getLogger(Config.class); 39 | 40 | private String adapterID="TEST"; 41 | private String tty; 42 | private String ttyIP; 43 | private Integer ttyPort; 44 | private String ttyType; 45 | private int ttyTimeOut = 2000; //default 46 | private int port = 31113; // default: unassigned Port. See: http://www.iana.org 47 | private String deviceType; 48 | private String protocol; 49 | private List thingList; 50 | 51 | 52 | 53 | Config(String fileName) throws Exception { 54 | thingList = new ArrayList(); 55 | // create XMLReader 56 | XMLReader xmlReader = XMLReaderFactory.createXMLReader(); 57 | 58 | log.debug("Try to open File {}", fileName); 59 | // Pfad tho XML Datei 60 | FileReader reader = new FileReader(fileName); 61 | InputSource inputSource = new InputSource(reader); 62 | 63 | log.info("File {} open for parsing", fileName); 64 | 65 | 66 | // set ContentHandler 67 | xmlReader.setContentHandler(new xHandler()); 68 | 69 | // start parser 70 | log.debug("Start parsing"); 71 | xmlReader.parse(inputSource); 72 | log.info("{} Things are parsed", thingList.size()); 73 | } 74 | 75 | 76 | public List getThingList() { 77 | return thingList; 78 | } 79 | 80 | private void addThing(Thing thing) { 81 | log.trace("Add thing id: {}", thing.getId()); 82 | thingList.add(new Thing(thing)); 83 | } 84 | 85 | public Thing getThing(String id) { 86 | log.trace("get thing id: {}", id); 87 | for (int i = 0; i < thingList.size(); i++) { 88 | if (thingList.get(i).getId().equals(id)) return thingList.get(i); 89 | } 90 | log.error("Add thing id: {} not found", id); 91 | return null; 92 | } 93 | 94 | 95 | private void setAdapterID(String s) { 96 | adapterID = s; 97 | log.info("Set adapterID: {}", adapterID); 98 | } 99 | 100 | public String getAdapterID() { 101 | return adapterID; 102 | } 103 | 104 | private void setTTY(String s) { 105 | tty = s; 106 | log.info("Set tty: {}", tty); 107 | } 108 | 109 | public String getTTY() { 110 | return tty; 111 | } 112 | 113 | private void setTTYType(String s) { 114 | ttyType = s; 115 | log.info("Set ttyType: {}", ttyType); 116 | } 117 | 118 | public String getTTYType() { 119 | return ttyType; 120 | } 121 | 122 | private void setTTYIP (String s) { 123 | ttyIP = s; 124 | log.info("Set ttyIP: {}", ttyIP); 125 | } 126 | 127 | public String getTTYIP() { 128 | return ttyIP; 129 | } 130 | 131 | private void setTTYPort(String s) { 132 | try { 133 | ttyPort = Integer.parseInt(s); 134 | } catch (NumberFormatException e) { 135 | log.error("Wrong Format for Port: {}", s); 136 | } 137 | log.info("Set TTY Port: {}", ttyPort); 138 | } 139 | 140 | public int getTTYPort() { 141 | return ttyPort; 142 | } 143 | 144 | private void setPort(String s) { 145 | try { 146 | port = Integer.parseInt(s); 147 | } catch (NumberFormatException e) { 148 | log.error("Wrong Format for Port: {}", s); 149 | } 150 | log.info("Set Socket Port: {}", port); 151 | } 152 | 153 | public int getPort() { 154 | return port; 155 | } 156 | 157 | 158 | private void setTtyTimeOut(String s) { 159 | try { 160 | ttyTimeOut = Integer.parseInt(s); 161 | } catch (NumberFormatException e) { 162 | log.error("Wrong Format for TTY Timeout: {}", s); 163 | } 164 | log.info("Set TTY Timeout: {} Milliseconds", ttyTimeOut); 165 | } 166 | 167 | public int getTtyTimeOut() { 168 | return ttyTimeOut; 169 | } 170 | 171 | 172 | public String getDeviceType() { 173 | return deviceType; 174 | } 175 | 176 | public String getProtocol() { 177 | return protocol; 178 | } 179 | 180 | 181 | // Handler for reading xml-Tags 182 | public class xHandler implements ContentHandler { 183 | 184 | private Thing thing = null; 185 | private Channel channel = null; 186 | private String path; 187 | private String[] urlPort; 188 | final String IPADDRESS_PATTERN = 189 | "^([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." + 190 | "([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." + 191 | "([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." + 192 | "([01]?\\d\\d?|2[0-4]\\d|25[0-5]):([0-9]{1,5})$"; 193 | 194 | @Override 195 | public void characters(char[] ch, int start, int length) 196 | throws SAXException { 197 | String s = new String(ch, start, length); 198 | switch (path) { 199 | case "root.optolink.tty": 200 | if (s.matches(IPADDRESS_PATTERN)) { // device is at an URL 201 | setTTYType ("URL"); 202 | setTTY(s); 203 | urlPort = s.split(":"); 204 | setTTYIP (urlPort[0]); 205 | setTTYPort (urlPort[1]); 206 | } else { // device is local 207 | setTTYType ("GPIO"); 208 | setTTY(s); 209 | } 210 | break; 211 | case "root.optolink.ttytimeout": 212 | setTtyTimeOut(s); 213 | break; 214 | case "root.optolink.port": 215 | setPort(s); 216 | break; 217 | case "root.optolink.adapterID": 218 | setAdapterID(s); 219 | break; 220 | case "root.optolink.thing.description": 221 | thing.setDescription(s); 222 | break; 223 | case "root.optolink.thing.channel.description": 224 | channel.setDescription(s); 225 | break; 226 | } 227 | 228 | } 229 | 230 | @Override 231 | public void endDocument() throws SAXException { 232 | // TODO Auto-generated method stub 233 | 234 | } 235 | 236 | @Override 237 | public void endElement(String uri, String localName, String pName) 238 | throws SAXException { 239 | 240 | if (localName.equals("thing")) { 241 | addThing(thing); 242 | } 243 | if (localName.equals("channel")) { 244 | thing.addChannel(channel);; 245 | } 246 | path = path.substring(0, path.lastIndexOf('.')); 247 | } 248 | 249 | @Override 250 | public void startDocument() throws SAXException { 251 | path = "root"; 252 | 253 | } 254 | 255 | @Override 256 | public void startElement(String uri, String localName, String pName, 257 | Attributes attr) throws SAXException { 258 | path = path + "." + localName; 259 | switch (path) { 260 | case "root.optolink": 261 | deviceType = attr.getValue("device"); 262 | protocol = attr.getValue("protocol"); 263 | break; 264 | case "root.optolink.thing": 265 | thing = new Thing(attr.getValue("id"), attr.getValue("type")); 266 | break; 267 | case "root.optolink.thing.channel": 268 | channel = new Channel (attr.getValue("id")); 269 | break; 270 | case "root.optolink.thing.channel.telegram": 271 | channel.setTelegram(new Telegram(attr.getValue("address"), 272 | attr.getValue("type"), 273 | attr.getValue("divider"))); 274 | break; 275 | 276 | } 277 | 278 | } 279 | 280 | @Override 281 | public void endPrefixMapping(String prefix) throws SAXException { 282 | // Not use Auto-generated method stub 283 | 284 | } 285 | 286 | @Override 287 | public void ignorableWhitespace(char[] ch, int start, int length) 288 | throws SAXException { 289 | // Not use Auto-generated method stub 290 | 291 | } 292 | 293 | @Override 294 | public void processingInstruction(String target, String data) 295 | throws SAXException { 296 | // Not use Auto-generated method stub 297 | 298 | } 299 | 300 | @Override 301 | public void setDocumentLocator(Locator locator) { 302 | // Not use Auto-generated method stub 303 | 304 | } 305 | 306 | @Override 307 | public void skippedEntity(String name) throws SAXException { 308 | // Not use Auto-generated method stub 309 | 310 | } 311 | 312 | @Override 313 | public void startPrefixMapping(String prefix, String uri) 314 | throws SAXException { 315 | // Not use Auto-generated method stub 316 | 317 | } 318 | 319 | } // Handler 320 | 321 | } 322 | -------------------------------------------------------------------------------- /src/main/java/de/myandres/optolink/Main.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2015, Stefan Andres. All rights reserved. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the GNU Lesser General Public License 6 | * (LGPL) version 3.0 which accompanies this distribution, and is available at 7 | * http://www.gnu.org/licenses/lgpl-3.0.html 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | *******************************************************************************/ 14 | package de.myandres.optolink; 15 | 16 | import org.slf4j.Logger; 17 | import org.slf4j.LoggerFactory; 18 | 19 | public class Main { 20 | 21 | static Logger log = LoggerFactory.getLogger(Main.class); 22 | 23 | // Central Classes, singular only!! 24 | static Config config; 25 | static ViessmannHandler viessmannHandler; 26 | static OptolinkInterface optolinkInterface; 27 | 28 | public static void main(String[] args) { 29 | // TODO Auto-generated method stub 30 | 31 | log.info("Programm gestartet"); 32 | 33 | try { 34 | 35 | // config = new Config("src/main/resources/optolink.xml"); 36 | config = new Config("conf/optolink.xml"); 37 | 38 | // Init TTY Handling for Optolink 39 | optolinkInterface = new OptolinkInterface(config); 40 | 41 | // Init ViessmannHandler 42 | viessmannHandler = new ViessmannHandler(config, optolinkInterface); 43 | 44 | } catch (Exception e) { 45 | log.error("Something is wrong not init", e); 46 | viessmannHandler.close(); 47 | optolinkInterface.close(); 48 | System.exit(1); 49 | } 50 | 51 | // Install catcher for Kill Signal 52 | Runtime.getRuntime().addShutdownHook(new Thread() { 53 | @Override 54 | public void run() { 55 | viessmannHandler.close(); 56 | optolinkInterface.close(); 57 | log.info("Programm normal terminated by Signal (Kill)"); 58 | } 59 | }); 60 | 61 | try { 62 | 63 | // Start SocketHandler 64 | SocketHandler socketHandler = new SocketHandler(config, viessmannHandler); 65 | socketHandler.start(); 66 | 67 | } catch (Exception e) { 68 | log.error("Programm abnormal terminated.", e); 69 | } 70 | 71 | } 72 | 73 | } 74 | -------------------------------------------------------------------------------- /src/main/java/de/myandres/optolink/OptolinkInterface.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2015, Stefan Andres. All rights reserved. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the GNU Lesser General Public License 6 | * (LGPL) version 3.0 which accompanies this distribution, and is available at 7 | * http://www.gnu.org/licenses/lgpl-3.0.html 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | *******************************************************************************/ 14 | package de.myandres.optolink; 15 | 16 | import gnu.io.CommPort; 17 | import gnu.io.CommPortIdentifier; 18 | import gnu.io.SerialPort; 19 | import java.io.IOException; 20 | import java.io.InputStream; 21 | import java.io.OutputStream; 22 | import java.net.Socket; 23 | import java.net.SocketTimeoutException; 24 | 25 | import org.slf4j.Logger; 26 | import org.slf4j.LoggerFactory; 27 | 28 | public class OptolinkInterface { 29 | 30 | static Logger log = LoggerFactory.getLogger(OptolinkInterface.class); 31 | 32 | private OutputStream output; 33 | private InputStream input; 34 | private Config config; 35 | private CommPortIdentifier portIdentifier; 36 | private CommPort commPort; 37 | private Socket socket = null; 38 | 39 | 40 | //TODO implement as runnable for URL-based optolinks 41 | 42 | OptolinkInterface(Config config) throws Exception { 43 | 44 | // constructor with implicit open 45 | this.config = config; 46 | if (this.config.getTTYType().matches("URL")) { // device is at an URL 47 | open(); 48 | close(); 49 | log.debug("TTY type URL is present"); 50 | } else { // device is local 51 | log.debug("Open TTY {} ...", this.config.getTTY()); 52 | portIdentifier = CommPortIdentifier.getPortIdentifier(this.config.getTTY()); 53 | 54 | if (portIdentifier.isCurrentlyOwned()) { 55 | log.error("TTY {} in use.", this.config.getTTY()); 56 | throw new IOException(); 57 | } 58 | commPort = portIdentifier.open(this.getClass().getName(), this.config.getTtyTimeOut()); 59 | if (commPort instanceof SerialPort) { 60 | SerialPort serialPort = (SerialPort) commPort; 61 | serialPort.setSerialPortParams(4800, SerialPort.DATABITS_8, 62 | SerialPort.STOPBITS_2, SerialPort.PARITY_EVEN); 63 | 64 | input = serialPort.getInputStream(); 65 | output = serialPort.getOutputStream(); 66 | commPort.enableReceiveTimeout(this.config.getTtyTimeOut()); // Reading Time-Out 67 | } 68 | log.debug("TTY {} opened", this.config.getTTY()); 69 | } 70 | } 71 | 72 | public synchronized void close() { 73 | if (this.config.getTTYType().matches("URL")) { 74 | log.debug("Close TTY type URL {} ....", this.config.getTTY()); 75 | if (socket != null) { 76 | try { 77 | socket.close(); 78 | log.debug("TTY type URL {} closed", this.config.getTTY()); 79 | } catch (IOException e) { 80 | log.debug("TTY type URL {} can't be closed", this.config.getTTY()); 81 | } 82 | } 83 | } else { 84 | log.debug("Close TTY {} ....", this.config.getTTY()); 85 | commPort.close(); 86 | log.debug("TTY {} closed", this.config.getTTY()); 87 | } 88 | } 89 | 90 | public synchronized void open() throws Exception { 91 | if (this.config.getTTYType().matches("URL")) { 92 | log.debug("Open TTY type URL {}", this.config.getTTY()); 93 | socket = new Socket (this.config.getTTYIP(), this.config.getTTYPort()); 94 | socket.setSoTimeout (this.config.getTtyTimeOut()); 95 | input = socket.getInputStream(); 96 | output = socket.getOutputStream(); 97 | log.debug("TTY type URL is open"); 98 | } 99 | } 100 | 101 | public synchronized void flush() { 102 | // Flush input Buffer 103 | if (this.config.getTTYType().matches("URL")) { 104 | // We have to wait a certain time. It seems that input.available always has the count 0 105 | // right after connecting 106 | try { 107 | Thread.sleep(30); // 10 ms is too low. 30 ms chosen for a certain fail safe distance 108 | } catch (InterruptedException e) { 109 | log.debug("Error while sleeping to wait for buffer flush"); 110 | } 111 | } 112 | try { 113 | input.skip(input.available()); 114 | log.debug("Input Buffer flushed"); 115 | } catch (IOException e) { 116 | log.error("Can't flush TTY: {}", this.config.getTTY(), e); 117 | } 118 | } 119 | 120 | public synchronized void write(int data) { 121 | log.trace("TxD: {}", String.format("%02X", (byte) data)); 122 | try { 123 | output.write((byte) data); 124 | } catch (IOException e) { 125 | log.error("Can't write Data to TTY {}", this.config.getTTY(), e); 126 | } 127 | } 128 | 129 | public synchronized int read() { 130 | int data = -1; 131 | try { 132 | data = input.read(); 133 | log.trace("RxD: {}", String.format("%02X", data)); 134 | if (data == -1) log.trace("Timeout from TTY {}", this.config.getTTY()); 135 | return data; 136 | } catch (SocketTimeoutException e) { 137 | log.trace("Timeout from TTY {}", this.config.getTTY()); 138 | return data; 139 | } catch (Exception e) { 140 | log.error("Can't read Data from TTY {}", this.config.getTTY(), e); 141 | } 142 | return -1; // Ups 143 | 144 | } 145 | 146 | public String getDeviceName() { 147 | return this.config.getDeviceType(); 148 | } 149 | 150 | } 151 | -------------------------------------------------------------------------------- /src/main/java/de/myandres/optolink/SocketHandler.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2015, Stefan Andres. All rights reserved. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the GNU Lesser General Public License 6 | * (LGPL) version 3.0 which accompanies this distribution, and is available at 7 | * http://www.gnu.org/licenses/lgpl-3.0.html 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | *******************************************************************************/ 14 | package de.myandres.optolink; 15 | 16 | /* 17 | * Install a Socked Handler for ip communication 18 | * 19 | * Server can found via Broadcast 20 | * Server API Client can connect via TCP 21 | * 22 | */ 23 | 24 | import java.io.BufferedReader; 25 | import java.io.InputStreamReader; 26 | import java.io.PrintStream; 27 | import java.net.ServerSocket; 28 | import java.net.Socket; 29 | 30 | import org.slf4j.Logger; 31 | import org.slf4j.LoggerFactory; 32 | 33 | public class SocketHandler { 34 | 35 | static Logger log = LoggerFactory.getLogger(SocketHandler.class); 36 | 37 | private Config config; 38 | private ServerSocket server; 39 | private ViessmannHandler viessmannHandler; 40 | private PrintStream out; 41 | 42 | SocketHandler(Config config, ViessmannHandler viessmannHandler) throws Exception { 43 | 44 | this.config = config; 45 | this.viessmannHandler = viessmannHandler; 46 | 47 | server = new ServerSocket(config.getPort()); 48 | } 49 | 50 | public void start() { 51 | 52 | BroadcastListner broadcastListner = new BroadcastListner(config.getPort(), config.getAdapterID()); 53 | 54 | // Put broadcast listner in background 55 | 56 | Thread broadcastListnerThread = new Thread(broadcastListner); 57 | broadcastListnerThread.setName("BcListner"); 58 | broadcastListnerThread.start(); 59 | 60 | // Wait connection 61 | 62 | while (true) { 63 | try { 64 | log.info("Listen on port {} for connection", config.getPort()); 65 | Socket socket = server.accept(); 66 | log.info("Connection on port {} accept. Remote host {}", config.getPort(), 67 | socket.getRemoteSocketAddress()); 68 | open(socket); 69 | } 70 | 71 | catch (Exception e) { 72 | log.info("Connection on Socket {} rejected or closed by client", config.getPort()); 73 | } 74 | } 75 | } 76 | 77 | private void open(Socket socket) throws Exception { 78 | 79 | BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream())); 80 | out = new PrintStream(socket.getOutputStream()); 81 | 82 | out.println(""); 83 | out.println(""); 84 | 85 | String inStr; 86 | 87 | while (true) { 88 | inStr = in.readLine(); 89 | if (inStr.toLowerCase().startsWith("exit")) { 90 | break; 91 | } 92 | if (!inStr.equals(null)) { 93 | new Thread(new CommandExec(inStr)).start(); 94 | } 95 | } 96 | 97 | out.println(""); 98 | 99 | } 100 | 101 | // Start a thread for each call command: No blocking of caller 102 | 103 | public class CommandExec implements Runnable { 104 | 105 | String param; 106 | 107 | CommandExec(String param) { 108 | this.param = param; 109 | } 110 | 111 | @Override 112 | public void run() { 113 | String command; 114 | String param1; 115 | String param2; 116 | 117 | log.debug("Execute Thread for: '{}'", param); 118 | String[] inStr = param.trim().split(" +"); 119 | command = inStr[0]; 120 | if (inStr.length > 1) { 121 | param1 = inStr[1]; 122 | } else { 123 | param1 = ""; 124 | } 125 | if (inStr.length > 2) { 126 | param2 = inStr[2]; 127 | } else { 128 | param2 = ""; 129 | } 130 | exec(command, param1, param2); 131 | log.debug("Thread for: '{}' done", param); 132 | } 133 | 134 | } 135 | 136 | private synchronized void exec(String command, String param1, String param2) { 137 | 138 | if (log.isTraceEnabled()) { 139 | log.trace("Queue Command: |{}|", command); 140 | log.trace(" param1 : |{}|", param1); 141 | log.trace(" param2 : |{}|", param2); 142 | } 143 | 144 | switch (command.toLowerCase()) { 145 | 146 | case "list": 147 | list(); 148 | break; 149 | case "get": 150 | if (param2.equals("")) { 151 | getThing(param1); 152 | } else { 153 | getThing(param1, param2); 154 | } 155 | break; 156 | case "set": 157 | set(param1, param2); 158 | break; 159 | default: 160 | log.error("Unknown Client Command:", command); 161 | 162 | log.trace("Queue Command: |{}| done", command); 163 | 164 | } 165 | 166 | } 167 | 168 | private void set(String id, String value) { 169 | // Format id = : 170 | 171 | String[] ids = id.trim().split(":"); 172 | 173 | if (ids.length != 2) { 174 | log.error("Wrong format '{}' of id", id); 175 | return; 176 | } 177 | Telegram telegram = config.getThing(ids[0]).getChannel(ids[1]).getTelegram(); 178 | if (telegram != null) { 179 | out.println(""); 180 | out.println(" "); 181 | 182 | out.println(" "); 184 | out.println(" "); 185 | out.println(""); 186 | } 187 | 188 | } 189 | 190 | private void getThing(String id) { 191 | log.debug("Try to get Thing for ID: {}", id); 192 | Thing thing = config.getThing(id); 193 | if (thing != null) { 194 | out.println(""); 195 | out.println(" "); 196 | for (Channel channel : thing.getChannelMap()) { 197 | if (!channel.getId().startsWith("*")) { 198 | out.println(" "); 200 | } 201 | } 202 | out.println(" "); 203 | out.println(""); 204 | } 205 | } 206 | 207 | private void getThing(String id, String channels) { 208 | Channel channel; 209 | log.debug("Try to get Thing for ID: {} channels: {}", id, channels); 210 | String[] channelList = channels.split(","); 211 | Thing thing = config.getThing(id); 212 | if (thing != null) { 213 | out.println(""); 214 | out.println(" "); 215 | for (int i = 0; i < channelList.length; i++) { 216 | channel = thing.getChannel(channelList[i]); 217 | if (channel != null) { 218 | out.println(" "); 220 | } else { 221 | log.error("Channel : {}.{} not define! ", id, channelList[i]); 222 | } 223 | } 224 | out.println(" "); 225 | out.println(""); 226 | } 227 | } 228 | 229 | private void list() { 230 | log.debug("List Things for ID"); 231 | out.println(""); 232 | for (Thing thing : config.getThingList()) { 233 | 234 | if ((thing != null) && !thing.getId().startsWith("*")) { 235 | 236 | out.println(" "); 237 | // out.println(" "); 238 | for (Channel channel : thing.getChannelMap()) { 239 | if (!channel.getId().startsWith("*")) { 240 | out.println(" "); 241 | // out.println(" " + channel.getDescription() + ""); 242 | // out.println(" "); 243 | } 244 | } 245 | out.println(" "); 246 | 247 | } 248 | } 249 | out.println(""); 250 | 251 | } 252 | 253 | } 254 | -------------------------------------------------------------------------------- /src/main/java/de/myandres/optolink/Telegram.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2015, Stefan Andres. All rights reserved. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the GNU Lesser General Public License 6 | * (LGPL) version 3.0 which accompanies this distribution, and is available at 7 | * http://www.gnu.org/licenses/lgpl-3.0.html 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | *******************************************************************************/ 14 | package de.myandres.optolink; 15 | 16 | import org.slf4j.Logger; 17 | import org.slf4j.LoggerFactory; 18 | 19 | public class Telegram { 20 | 21 | static Logger log = LoggerFactory.getLogger(Telegram.class); 22 | 23 | // Types of Viessmann 24 | public final static byte BOOLEAN = 1; // 1 Byte -> boolean 25 | public final static byte BYTE = 2; // 1 Byte -> short 26 | public final static byte UBYTE = 3; // 1 Byte -> short 27 | public final static byte SHORT = 4; // 2 Byte -> int 28 | public final static byte USHORT = 5; // 2 Byte -> int 29 | public final static byte INT = 6; // 4 byte -> long 30 | public final static byte UINT = 7; // 4 Byte -> long 31 | public final static byte DATE = 8; // 8 Byte -> date 32 | public final static byte TIMER = 9; // 8 Byte -> timer 33 | public final static byte DUMP = 99; // Dump for unknown Telegram-Type 34 | 35 | 36 | private int address; 37 | private byte type; 38 | private short length; 39 | private short divider; 40 | 41 | 42 | Telegram() { 43 | address = 0; 44 | type = Telegram.DUMP; 45 | length = 0; 46 | divider = 1; 47 | } 48 | 49 | Telegram(String address, String type, String divider) { 50 | 51 | setAddress(address); 52 | setType(type); 53 | setDivider(divider); 54 | } 55 | 56 | Telegram(Telegram telegram) { 57 | 58 | this.address = telegram.address; 59 | this.length = telegram.length; 60 | this.type = telegram.type; 61 | this.divider = telegram.divider; 62 | 63 | } 64 | 65 | 66 | public void setAddress(String address) { 67 | log.trace("----------------------------------------"); 68 | 69 | if (address==null) { 70 | log.error("Telegram Address not set") ; 71 | this.address=0; 72 | } else { 73 | try { 74 | this.address = Integer.parseInt(address,16); 75 | } catch (NumberFormatException e) { 76 | log.error("Invalid Address format: {}", address); 77 | this.address=0; 78 | } 79 | } 80 | log.trace("Set Adress to {}({})", address, this.address); 81 | } 82 | 83 | 84 | 85 | public void setType(String type) { 86 | if (type == null) 87 | log.error("Telegram Type not set"); 88 | else { 89 | switch (type.toLowerCase()) { 90 | case "boolean": 91 | this.type = Telegram.BOOLEAN; 92 | length=1; 93 | break; 94 | case "byte": 95 | this.type = Telegram.BYTE; 96 | length=1; 97 | break; 98 | case "ubyte": 99 | this.type = Telegram.UBYTE; 100 | length=1; 101 | break; 102 | case "short": 103 | this.type = Telegram.SHORT; 104 | length=2; 105 | break; 106 | case "ushort": 107 | this.type = Telegram.USHORT; 108 | length=2; 109 | break; 110 | case "int": 111 | this.type = Telegram.INT; 112 | length=4; 113 | break; 114 | case "uint": 115 | this.type = Telegram.UINT; 116 | length=4; 117 | break; 118 | case "date": 119 | this.type = Telegram.DATE; 120 | length=8; 121 | break; 122 | case "timer": 123 | this.type = Telegram.TIMER; 124 | length=8; 125 | break; 126 | default: { 127 | log.error("Unknown Type: {}", type); 128 | this.type = Telegram.DUMP; 129 | length=0; 130 | 131 | } 132 | } 133 | } 134 | log.trace("Set Type to {}({}) length={}", type, this.type, length); 135 | } 136 | 137 | public void setDivider(String divider) { 138 | if (divider==null) { 139 | log.debug("divider not set - set to default: 1"); 140 | this.divider=1; 141 | } else { 142 | try { 143 | this.divider=Short.parseShort(divider); 144 | } 145 | catch (NumberFormatException e) { 146 | log.error("Invalid divider format: {} - set to default: 1", divider); 147 | this.divider=1; 148 | } 149 | } 150 | log.trace("Set dividerider to {}", this.divider); 151 | } 152 | 153 | 154 | public int getAddress() { 155 | return address; 156 | } 157 | 158 | public String getAddressAsString() { 159 | return String.format("%04X", address); 160 | } 161 | 162 | 163 | public int getLength() { 164 | return length; 165 | } 166 | 167 | 168 | public short getDivider() { 169 | return divider; 170 | } 171 | 172 | public byte getType() { 173 | return type; 174 | } 175 | 176 | } 177 | -------------------------------------------------------------------------------- /src/main/java/de/myandres/optolink/Thing.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2015, Stefan Andres. All rights reserved. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the GNU Lesser General Public License 6 | * (LGPL) version 3.0 which accompanies this distribution, and is available at 7 | * http://www.gnu.org/licenses/lgpl-3.0.html 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | *******************************************************************************/ 14 | package de.myandres.optolink; 15 | 16 | import java.util.List; 17 | import java.util.ArrayList; 18 | import java.util.HashMap; 19 | import java.util.Map; 20 | 21 | import org.slf4j.Logger; 22 | import org.slf4j.LoggerFactory; 23 | 24 | public class Thing { 25 | 26 | static Logger logger = LoggerFactory.getLogger(Thing.class); 27 | 28 | private String type; 29 | private String id; 30 | private String description; 31 | private Map channelMap = new HashMap(); 32 | 33 | public List getChannelMap() { 34 | return new ArrayList(channelMap.values()); 35 | } 36 | 37 | Thing(String id, String type) { 38 | logger.trace("Init type: '{}' id: '{}'", type, id ); 39 | channelMap.clear(); 40 | this.type = type; 41 | this.id = id; 42 | this.description = null;; 43 | } 44 | 45 | Thing(Thing thing) { 46 | logger.trace("Init type: '{}' id: '{}'", thing.type, thing.id ); 47 | channelMap.clear(); 48 | this.channelMap = thing.channelMap; 49 | this.type = thing.type; 50 | this.id = thing.id; 51 | this.description = thing.description; 52 | 53 | } 54 | 55 | public String getType() { 56 | return type; 57 | } 58 | 59 | public void setType(String type) { 60 | this.type = type; 61 | } 62 | 63 | public String getId() { 64 | return id; 65 | } 66 | 67 | public void setId(String id) { 68 | this.id = id; 69 | } 70 | 71 | public String getDescription() { 72 | return description; 73 | } 74 | 75 | public void setDescription(String description) { 76 | this.description = description; 77 | } 78 | 79 | public void addChannel(Channel channel) { 80 | channelMap.put(channel.getId(), new Channel(channel)); 81 | } 82 | 83 | public Channel getChannel(String id) { 84 | return channelMap.get(id); 85 | } 86 | 87 | 88 | } 89 | -------------------------------------------------------------------------------- /src/main/java/de/myandres/optolink/Viessmann300.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2015, Stefan Andres. All rights reserved. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the GNU Lesser General Public License 6 | * (LGPL) version 3.0 which accompanies this distribution, and is available at 7 | * http://www.gnu.org/licenses/lgpl-3.0.html 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | *******************************************************************************/ 14 | package de.myandres.optolink; 15 | 16 | import org.slf4j.Logger; 17 | import org.slf4j.LoggerFactory; 18 | 19 | public class Viessmann300 implements ViessmannProtocol { 20 | 21 | static Logger log = LoggerFactory.getLogger(Viessmann300.class); 22 | 23 | private OptolinkInterface optolinkInterface; 24 | 25 | 26 | Viessmann300(OptolinkInterface optolinkInterface) { 27 | log.trace("Start Session for Protokoll '300' ...."); 28 | this.optolinkInterface = optolinkInterface; 29 | startSession(); 30 | log.trace("Start Session for Protokoll '300' started"); 31 | } 32 | 33 | 34 | @Override 35 | public synchronized int getData (byte[] buffer, int address, int length) { 36 | 37 | byte[] localBuffer = new byte[16]; 38 | int returNumberOfBytes; 39 | 40 | for (int i=0; i<3; i++) { 41 | 42 | log.debug(String.format("Get Data for address %04X .... ", address)); 43 | 44 | // construct TxD 45 | 46 | localBuffer[0] = 0x00; // Request 47 | localBuffer[1] = 0x01; // reading Data 48 | localBuffer[2] = (byte)(address >> 8); // upper Byte of address 49 | localBuffer[3] = (byte)(address & 0xff); // lower Byte of address 50 | localBuffer[4] = (byte)length; // number of expected bytes 51 | 52 | 53 | if ( transmit(localBuffer,5)) {; // send Buffer 54 | 55 | // RxD 56 | returNumberOfBytes = receive(localBuffer); // read answer 57 | 58 | if (returNumberOfBytes > 0) { 59 | 60 | // check RxD 61 | int returnAddress; 62 | if (localBuffer[0] == 0x03) log.error("Answer Byte is 0x03: Return Error(Wrong Adress,maybe)"); 63 | if (localBuffer[0] != 0x01) log.error("Answer Byte (0x01) expect, but: 0x{} received", String.format("%02X", localBuffer[0])); 64 | if (localBuffer[1] != 0x01) log.error("DataRead Byte (0x01) expect, but: 0x{} received", String.format("%02X",buffer[1])); 65 | returnAddress = ((localBuffer[2] & 0xFF) << 8) + ((int)localBuffer[3] & 0xFF); // Address 66 | if (returnAddress != address) log.error(String.format("Adress (%04X) expect, but: %04X received", address, returnAddress)); 67 | for (int j=0;j> 8); // upper Byte of address 95 | localBuffer[3] = (byte)(address & 0xff); // lower Byte of address 96 | localBuffer[4] = (byte)length; // number bytes 97 | switch (length) { 98 | case 1: localBuffer[5] = (byte)(value & 0xff); 99 | break; 100 | case 2: localBuffer[5] = (byte)(value >> 8); 101 | localBuffer[6] = (byte)(value & 0xff); 102 | break; 103 | case 4: localBuffer[5] = (byte)(value >> 24); 104 | localBuffer[6] = (byte)(value >> 16); 105 | localBuffer[7] = (byte)(value >> 8); 106 | localBuffer[8] = (byte)(value & 0xff); 107 | break; 108 | } 109 | 110 | if ( transmit(localBuffer,5+length)) {; // send Buffer 111 | 112 | // RxD 113 | returNumberOfBytes = receive(localBuffer); // read answer 114 | 115 | if (returNumberOfBytes > 0) { 116 | 117 | // check RxD 118 | int returnAddress; 119 | if (localBuffer[0] == 0x03) 120 | log.error("Answer Byte is 0x03: Return Error(Wrong Adress,maybe)"); 121 | if (localBuffer[0] != 0x01) 122 | log.error("Answer Byte (0x01) expect, but: 0x{} received", 123 | String.format("%02X", localBuffer[0])); 124 | if (localBuffer[1] != 0x02) 125 | log.error("Data Write Byte (0x02) expect, but: 0x{} received", 126 | String.format("%02X",buffer[1])); 127 | returnAddress = ((localBuffer[2] & 0xFF) << 8) + ((int)localBuffer[3] & 0xFF); // Address 128 | if (returnAddress != address) 129 | log.error(String.format("Adress (%04X) expect, but: %04X received", address, returnAddress)); 130 | for (int j=0;j 23 | hr < 0 | min > 59 | min < 0) { 88 | log.error("Invalid time. Hour %d has to between 0 and 23 and Minute %d between 0 and 59", hr,min); 89 | return null; 90 | } 91 | hr = hr << 3; 92 | min = (int) min/10; 93 | buffer[i] = (byte) (hr | min); 94 | } 95 | for (int i = switchTimesLength; i < 8; i++) { 96 | buffer[i] = (byte) 0xff; 97 | } 98 | for (int i = 0; i < 8; i+=2) { 99 | if ((buffer[i] & 0xff) > (buffer[i+1] & 0xff)) { 100 | log.error("Invalid time pair. On time %02x if bigger than Off time %02x", buffer[i],buffer[i+1]); 101 | return null; 102 | } 103 | } 104 | } else { 105 | log.error("Error! SwitchTime has to be in on/off pairs"); 106 | return null; 107 | } 108 | locValue = 9; 109 | break; 110 | default : float fl = (new Float(value)) * telegram.getDivider(); // all other writable channels are byte or ubyte 111 | buffer[0] = (byte) fl; 112 | break; 113 | } 114 | if (this.config.getTTYType().matches("URL")) { 115 | try { 116 | optolinkInterface.open(); 117 | } catch (Exception e) { 118 | log.error("Opening TTY type URL failed"); 119 | optolinkInterface.close(); 120 | return null; 121 | } 122 | } 123 | int resultLength = viessmannProtocol.setData(buffer, telegram.getAddress() , telegram.getLength(), locValue); 124 | if (this.config.getTTYType().matches("URL")) { 125 | optolinkInterface.close(); 126 | } 127 | 128 | if (resultLength == 0) return null; 129 | else return formatValue(buffer, telegram.getType(), telegram.getDivider()); 130 | 131 | } 132 | 133 | 134 | 135 | public synchronized String getValue(Telegram telegram) { 136 | byte [] buffer = new byte[16]; 137 | 138 | if (this.config.getTTYType().matches("URL")) { 139 | try { 140 | optolinkInterface.open(); 141 | } catch (Exception e) { 142 | log.error("Opening TTY type URL failed"); 143 | optolinkInterface.close(); 144 | return null; 145 | } 146 | } 147 | int resultLength=viessmannProtocol.getData(buffer,telegram.getAddress(), telegram.getLength()); 148 | if (log.isTraceEnabled()) { 149 | log.trace("Number of Bytes: {}", resultLength); 150 | for (int i=0; i>3,(buffer[i] & 7)*10, (buffer[i+1] & 0xF8)>>3,(buffer[i+1] & 7)*10); 175 | } 176 | } 177 | return timer; 178 | case Telegram.DATE: 179 | return String.format("%02x%02x-%02x-%02xT%02x:%02x:%02x", 180 | buffer[0],buffer[1],buffer[2],buffer[3],buffer[5],buffer[6],buffer[7]) ; 181 | case Telegram.BYTE: 182 | result = buffer[0]; 183 | break; 184 | case Telegram.UBYTE: 185 | result = 0xFF & buffer[0]; 186 | break; 187 | case Telegram.SHORT: 188 | result = ((long)(buffer[1]))*0x100 + (long)(0xFF & buffer[0]); 189 | break; 190 | case Telegram.USHORT: 191 | result = ((long)(0xFF & buffer[1]))*0x100 + (long)(0xFF & buffer[0]); 192 | break; 193 | case Telegram.INT: 194 | result = ((long)(buffer[3]))*0x1000000 + ((long)(0xFF & buffer[2]))*0x10000 + ((long)(0xFF & buffer[1]))*0x100 + (long)(0xFF & buffer[0]); 195 | break; 196 | case Telegram.UINT: 197 | result = ((long)(0xFF & buffer[3]))*0x1000000 + ((long)(0xFF & buffer[2]))*0x10000 + ((long)(0xFF & buffer[1]))*0x100 + (long)(0xFF & buffer[0]); 198 | break; 199 | } 200 | if (divider !=1 ) 201 | return String.format(Locale.US,"%.2f", (float)result / divider); 202 | else return String.format("%d", result); 203 | 204 | 205 | } 206 | 207 | 208 | } 209 | -------------------------------------------------------------------------------- /src/main/java/de/myandres/optolink/ViessmannKW.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2015, Stefan Andres. All rights reserved. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the GNU Lesser General Public License 6 | * (LGPL) version 3.0 which accompanies this distribution, and is available at 7 | * http://www.gnu.org/licenses/lgpl-3.0.html 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | *******************************************************************************/ 14 | package de.myandres.optolink; 15 | 16 | import org.slf4j.Logger; 17 | import org.slf4j.LoggerFactory; 18 | 19 | public class ViessmannKW implements ViessmannProtocol { 20 | 21 | 22 | static Logger log = LoggerFactory.getLogger(ViessmannKW.class); 23 | 24 | private OptolinkInterface optolinkInterface; 25 | 26 | 27 | ViessmannKW(OptolinkInterface optolinkInterface) { 28 | log.trace("Start Session for Protokoll 'KW' ...."); 29 | this.optolinkInterface = optolinkInterface; 30 | log.trace("Start Session for Protokoll 'KW' started"); 31 | } 32 | 33 | 34 | @Override 35 | public int getData(byte[] buffer, int address, int length) { 36 | 37 | int j=0; 38 | optolinkInterface.flush(); 39 | while (optolinkInterface.read() != 0x05 ) { // Wait for 0x05 40 | if (j++ > 10) { 41 | log.error("Can't send Data to OptolinkInterface, missing 0x05"); 42 | log.error("!!!!!!!!!!!!!!!! Trouble with communication to OptolinkInterface !!!!!!!!" ); 43 | log.error("!!!!!!!!!!!!!!!! Pleace check hardware !!!!!!!!" ); 44 | return -1; 45 | } 46 | 47 | } 48 | optolinkInterface.write(0x01); // Answer to 0x05 49 | optolinkInterface.write(0xF7); // Read Data 50 | optolinkInterface.write((byte)(address >> 8)); // upper Byte of address 51 | optolinkInterface.write((byte)(address & 0xff)); // lower Byte of address 52 | optolinkInterface.write((byte)length); // number of expected bytes 53 | 54 | for (int i=0; i 10) { 76 | log.error("Can't send Data to OptolinkInterface, missing 0x05"); 77 | log.error("!!!!!!!!!!!!!!!! Trouble with communication to OptolinkInterface !!!!!!!!" ); 78 | log.error("!!!!!!!!!!!!!!!! Pleace check hardware !!!!!!!!" ); 79 | return -1; 80 | } 81 | 82 | } 83 | optolinkInterface.write(0x01); // Answer to 0x05 84 | optolinkInterface.write(0xF4); // write Data 85 | optolinkInterface.write((byte)(address >> 8)); // upper Byte of address 86 | optolinkInterface.write((byte)(address & 0xff)); // lower Byte of address 87 | optolinkInterface.write((byte)length); // number of expected bytes 88 | switch (length) { 89 | case 1: optolinkInterface.write(buffer[0]); // write lower byte 90 | break; 91 | case 8: optolinkInterface.write(buffer[0]); // Timer data has length 8 92 | optolinkInterface.write(buffer[1]); 93 | optolinkInterface.write(buffer[2]); 94 | optolinkInterface.write(buffer[3]); 95 | optolinkInterface.write(buffer[4]); 96 | optolinkInterface.write(buffer[5]); 97 | optolinkInterface.write(buffer[6]); 98 | optolinkInterface.write(buffer[7]); 99 | break; 100 | } 101 | return length; 102 | } 103 | 104 | } 105 | -------------------------------------------------------------------------------- /src/main/java/de/myandres/optolink/ViessmannProtocol.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2015, Stefan Andres. All rights reserved. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the GNU Lesser General Public License 6 | * (LGPL) version 3.0 which accompanies this distribution, and is available at 7 | * http://www.gnu.org/licenses/lgpl-3.0.html 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | *******************************************************************************/ 14 | package de.myandres.optolink; 15 | 16 | public interface ViessmannProtocol { 17 | 18 | public int getData(byte[] buffer, int address, int length); 19 | void close(); 20 | int setData(byte[] buffer, int address, int length, int value); 21 | 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/main/resources/INSTALL_AUTOSTART.txt: -------------------------------------------------------------------------------- 1 | To start the program at boottime: 2 | 3 | 1.) edit optolink.init.d (USER & HOME) 4 | 5 | 2.) sudo cp optolink.init.d /etc/init.d/optolink 6 | 7 | 3.) sudo 755 /etc/init.d/optolink 8 | 9 | 4.) sudo update-rc-d optolink defaults 10 | 11 | 12 | now optolink adapter going to start at boottime. 13 | -------------------------------------------------------------------------------- /src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | logs/optolink.log 7 | 8 | 9 | logs/optolink-%d{yyyy-ww}.log.zip 10 | 11 | 12 12 | 13 | 14 | %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} %M - %msg%n 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /src/main/resources/logback_debug.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | logs/optolink_debug.log 7 | 8 | 9 | logs/optolink-%d{yyyy-ww}.log.zip 10 | 11 | 12 12 | 13 | 14 | %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} %M - %msg%n 15 | 16 | 17 | 18 | 19 | 20 | %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} %M - %msg%n 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /src/main/resources/logback_trace.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | logs/optolink_trace.log 7 | 8 | 9 | logs/optolink-%d{yyyy-ww}.log.zip 10 | 11 | 12 12 | 13 | 14 | %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} %M - %msg%n 15 | 16 | 17 | 18 | 19 | 20 | %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} %M - %msg%n 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /src/main/resources/optolink-ob.xml: -------------------------------------------------------------------------------- 1 | 2 | 23 | 24 | 25 | 26 | 27 | 28 | VScotH01 29 | 192.168.178.25:10001 30 | 2000 31 | 31113 32 | 33 | 34 | 35 | 36 | Viessmann Vitodens 300-W 37 | 38 | System ID 39 | 40 | 41 | 42 | System Date and Time 43 | 44 | 45 | 46 | Outside Temperature 47 | 48 | 49 | 50 | General malfunction heating 51 | 52 | 53 | 54 | 55 | 56 | Hot Water Storage Tank an Buffer 57 | 58 | Hot water temperature. 59 | 60 | 61 | 62 | Hot water temperatur target temperature. 63 | 64 | 65 | 66 | Cirulation Pump for Hot Water TODO which pump? 67 | 68 | 69 | 70 | 71 | 72 | 73 | Burner 74 | 75 | The furnace Power in % 76 | 77 | 78 | 79 | Exhaust temperature 80 | 81 | 82 | 83 | Boiler temperature 84 | 85 | 86 | 87 | 88 | State of Burner 89 | 90 | 91 | 92 | 93 | 94 | 95 | Heading Circuit of the first Floor. 96 | 97 | Flow temperature 98 | 99 | 100 | 101 | pump 102 | 103 | 104 | 105 | Operation mode (0,1,2,3,4). 106 | 107 | 108 | 109 | Inside Temperature 110 | 111 | 112 | 113 | Room Set temperature. 114 | 115 | 116 | 117 | Timer Monday 118 | 119 | 120 | 121 | Timer Tuesday 122 | 123 | 124 | 125 | Timer Wednesday 126 | 127 | 128 | 129 | Timer Thursday 130 | 131 | 132 | 133 | Timer Friday 134 | 135 | 136 | 137 | Timer Saturday 138 | 139 | 140 | 141 | Timer Sunday 142 | 143 | 144 | 145 | Timer Monday 146 | 147 | 148 | 149 | Timer Tuesday 150 | 151 | 152 | 153 | Timer Wednesday 154 | 155 | 156 | 157 | Timer Thursday 158 | 159 | 160 | 161 | Timer Friday 162 | 163 | 164 | 165 | Timer Saturday 166 | 167 | 168 | 169 | Timer Sunday 170 | 171 | 172 | 173 | -------------------------------------------------------------------------------- /src/main/resources/optolink.init.d: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Start/stop the optolink 3 | # 4 | ### BEGIN INIT INFO 5 | # Provides: optolink 6 | # Default-Start: 2 3 4 5 7 | # Default-Stop: 8 | # Short-Description: Regular background program processing Viessmann optolink adapter 9 | ### END INIT INFO 10 | 11 | HOME=/home/pi/optolink 12 | USER=pi 13 | 14 | PATH=/bin:/usr/bin:/sbin:/usr/sbin 15 | 16 | test -f $HOME/start.sh || exit 0 17 | 18 | 19 | 20 | case "$1" in 21 | start) cd $HOME 22 | sudo -u $USER ./start.sh & 23 | ;; 24 | stop) cd $HOME 25 | ./stop.sh 26 | ;; 27 | restart) log_daemon_msg "Restarting periodic command scheduler" "cron" 28 | $0 stop 29 | $0 start 30 | ;; 31 | status) 32 | exit 0 33 | ;; 34 | *) log_action_msg "Usage: /etc/init.d/cron {start|stop|status|restart}" 35 | exit 2 36 | ;; 37 | esac 38 | exit 0 39 | -------------------------------------------------------------------------------- /src/main/resources/optolink.xml: -------------------------------------------------------------------------------- 1 | 2 | 22 | 23 | 24 | 25 | 26 | 27 | VITOLIGNO 28 | /dev/ttyAMA0 29 | 2000 30 | 31113 31 | 32 | 33 | 34 | 35 | Viessmann Vitoligno 300P 36 | 37 | System ID 38 | 39 | 40 | 41 | System Date and Time 42 | 43 | 44 | 45 | Outsite Temperature 46 | 47 | 48 | 49 | The furnace temperature of the burner boiler 50 | 51 | 52 | 53 | 54 | 55 | Hot Water Storage Tank an Buffer 56 | 57 | Hot water temperatur on top of the buffer. 58 | 59 | 60 | 61 | Temperature in the middle of the buffer 62 | 63 | 64 | 65 | Temperature on the bottom of the buffer 66 | 67 | 68 | 69 | Cirulation Pump for Hot Water 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | Burner/Fireplace 78 | 79 | The furnace Power in % 80 | 81 | 82 | 83 | O2 in % 84 | 85 | 86 | 87 | Primary air shutter % 88 | 89 | 90 | 91 | Secondary air shutter % 92 | 93 | 94 | 95 | actual Fanspeed 96 | 97 | 98 | 99 | target Fanspeed 100 | 101 | 102 | 103 | 104 | The furnace Power in % 105 | 106 | 107 | 108 | 109 | State of Burner 110 | 111 | 112 | 113 | Counts the number of starts sience first start of heating. 114 | 115 | 116 | 117 | On time of the burner sience first start of heating. 118 | 119 | 120 | 121 | Consumed Pellets since start of heating in t. 122 | 123 | 124 | 125 | return flow uprating 126 | 127 | 128 | 129 | 130 | 131 | Heading Circuit of the first Floor. 132 | 133 | Flow temperature 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | Party temperature. 142 | 143 | 144 | 145 | The savemode. 146 | 147 | 148 | 149 | Partymode. 150 | 151 | 152 | 153 | Party temperature. 154 | 155 | 156 | 157 | Party temperature. 158 | 159 | 160 | 161 | Save temperature. 162 | 163 | 164 | 165 | The gradient relativ to outsite temperature. 166 | 167 | 168 | 169 | The niveau relativ to outsite temperature. 170 | 171 | 172 | 173 | 174 | 175 | 176 | Heading Circuit of the first Floor. 177 | 178 | Flow temperature 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | Operation mode (0,1,2,3,4). 187 | 188 | 189 | 190 | The savemode. 191 | 192 | 193 | 194 | Partymode. 195 | 196 | 197 | 198 | Party temperature. 199 | 200 | 201 | 202 | Room temperature. 203 | 204 | 205 | 206 | Save temperature. 207 | 208 | 209 | 210 | The gradient relativ to outsite temperature. 211 | 212 | 213 | 214 | The niveau relativ to outsite temperature. 215 | 216 | 217 | 218 | 219 | 220 | 221 | Thermo Solar System. 222 | 223 | Collector temperature. 224 | 225 | 226 | 227 | Temperatur of storage tank (same storage tank bottom) 228 | 229 | 230 | 231 | Pump to load the storage tank from the solar panel. 232 | 233 | 234 | 235 | 236 | Load suppression 237 | 238 | 239 | 240 | On time of the solar pump in hours. 241 | 242 | 243 | 244 | Consumed power from the sun in KW. 245 | 246 | 247 | 248 | -------------------------------------------------------------------------------- /src/main/resources/start.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | PID=./optolink.pid 4 | 5 | 6 | prog_arg="-Dlogback.configurationFile=lib/logback.xml" 7 | prog_arg="${prog_arg} -Djava.library.path=/usr/lib/jni" 8 | prog_arg="${prog_arg} -Dgnu.io.rxtx.SerialPorts=/dev/ttyAMA0" 9 | 10 | 11 | java $prog_arg -jar lib/optolink-jar-with-dependencies.jar >/dev/null 2>&1 & 12 | echo $! >$PID 13 | 14 | echo "Optolink adapter started" -------------------------------------------------------------------------------- /src/main/resources/start_debug.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | 4 | prog_arg="-Dlogback.configurationFile=conf/logback_debug.xml" 5 | prog_arg="${prog_arg} -Djava.library.path=/usr/lib/jni" 6 | prog_arg="${prog_arg} -Dgnu.io.rxtx.SerialPorts=/dev/ttyAMA0" 7 | 8 | 9 | java $prog_arg -jar lib/optolink-jar-with-dependencies.jar -------------------------------------------------------------------------------- /src/main/resources/start_trace.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | 4 | prog_arg="-Dlogback.configurationFile=conf/logback_trace.xml" 5 | prog_arg="${prog_arg} -Djava.library.path=/usr/lib/jni" 6 | prog_arg="${prog_arg} -Dgnu.io.rxtx.SerialPorts=/dev/ttyAMA0" 7 | 8 | 9 | java $prog_arg -jar lib/optolink-jar-with-dependencies.jar -------------------------------------------------------------------------------- /src/main/resources/stop.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | PID=./optolink.pid 4 | 5 | 6 | if [ -f $PID ]; then 7 | ps `cat $PID` 8 | if [ $? == 0 ]; then 9 | kill `cat $PID` 10 | echo "Optolink adapter killed" 11 | rm $PID 12 | else 13 | echo "Prozess not found" 14 | exit 1 15 | fi 16 | else 17 | echo "File ${PID} found" 18 | exit 1 19 | fi 20 | --------------------------------------------------------------------------------