Power-Line Kommunikation
Oder: Mit JControl über die Steckdose kommunizieren
| |
Voraussetzungen: Für dieses Tutorial wird die Installation der JControl/IDE, ein JControl-basiertes Gerät mit Power-Line-Modem (z.B. das "JControl/PLUI", Power-Line User Interface, siehe Bild unten) sowie eine über Power-Line schaltbare Steckdose (Bild oben) vorausgesetzt.
Download: http://www.jcontrol.org/examples/PowerLineExample.zip Dieses Tutorial mit allen Quelltexten und Ressourcen als JControl/IDE-Projekt (ZIP-Archiv).
Das JControl/PLUI ist mit einem eingebauten Power-Line-Modem ausgestattet, welches den Datenaustausch mit einem anderen JControl/PLUI oder einem beliebigem Konnex-kompatiblen Power-Line-Gerät über die 230V-Stromversorgung ermöglicht. Ausführliche Informationen über die Power-Line-Technologie und den Konnex-Standard können z.B. auf der Domologic Homepage http://www.pl132.de nachgelesen werden.
Der Datenaustausch zwischen Power-Line-Modem und JControl-System findet über das standardisierte FT1.2-Protokoll statt (IEC EN60870-5-1). Dieses ist in der Klasse FT1_2
der JControl API http://www.jcontrol.org/current/docs/api/jcontrol/comm/FT1_2.html bereits implementiert und kann von Anwendungsprogrammen direkt verwendet werden. Das FT1.2-Protokoll sorgt für eine sichere Datenkommunikation, indem automatisch Prüfsummen berechnet und verifiziert werden. Bei Übertragungsfehlern werden die Datenpakete bis zu 3 mal wiederholt.
Der folgende Quelltext kann als allgemeines Grundgerüst für Anwendungen mit Power-Line-Kommunikation herangezogen werden. Er zeigt, wie die FT1_2
-Klasse initialisiert und ein FT1_2EventListener
installiert wird. Der Listener ist erforderlich, um eingehende Power-Line-Datagramme auf Java-Ebene zu empfangen.
1 | import java.io.IOException; |
2 | |
3 | import jcontrol.comm.FT1_2; |
4 | import jcontrol.comm.FT1_2EventListener; |
5 | import jcontrol.comm.RS232Selector; |
6 | import jcontrol.io.Buzzer; |
7 | |
8 | /** |
9 | * <p>Basic code for power-line communication using the <code>class |
10 | * FT1_2</code>.</p> |
11 | * |
12 | * <p>(C) DOMOLOGIC Home Automation GmbH 2003</p> |
13 | */ |
14 | public class PowerLineExample_Base implements FT1_2EventListener { |
15 | |
16 | /** FT1.2 protocol */ |
17 | static FT1_2 ft12; |
18 | |
19 | /** System buzzer */ |
20 | Buzzer buzzer = new Buzzer(); |
21 | |
22 | /** |
23 | * Init FT1.2 protocol |
24 | */ |
25 | public PowerLineExample_Base() { |
26 | // switch RS232 to power-line modem |
27 | RS232Selector.selectPort(RS232Selector.INTERNAL); |
28 | |
29 | try { |
30 | // instantiate FT1_2 protocol |
31 | ft12 = new FT1_2(); |
32 | // set ourself as the FT1_2EventListener |
33 | ft12.setListener(this); |
34 | } catch (java.io.IOException e) { |
35 | // 2 second error beep |
36 | buzzer.on((short)300, (short)2000); |
37 | // read errorcode to reset error flag |
38 | ft12.errorCode(); |
39 | } |
40 | } |
41 | |
42 | |
43 | /** |
44 | * FT1.2 event listener. This method is called any time |
45 | * a power-line datagram drops in. |
46 | * |
47 | * @see jcontrol.comm.FT1_2EventListener#onIndication(byte[], int) |
48 | */ |
49 | public void onIndication(byte[] udat, int control) { |
50 | try { |
51 | switch(control){ |
52 | case FT1_2.CF_PRM_SEND_UDAT: |
53 | ft12.sendACK(udat); |
54 | break; |
55 | case FT1_2.CF_PRM_REQ_STATUS: |
56 | ft12.sendResponse(null); |
57 | break; |
58 | case FT1_2.CF_PRM_REQ_CLASS1: |
59 | byte[] buf=new byte[10]; |
60 | ft12.sendResponse(buf); |
61 | break; |
62 | } |
63 | } catch(IOException e){} |
64 | } |
65 | |
66 | |
67 | /** |
68 | * Main method. Program execution starts here. |
69 | */ |
70 | public static void main(String[] args) { |
71 | new PowerLineExample_Base(); |
72 | } |
73 | } |
Zur Initialisierung der FT1.2-Kommunikation genügt die Instantiierung des Konstruktors. Um den RS232-Port des JControl/PLUI mit dem integrierten Power-Line-Modem zu verbinden, muss die Methode selectPort
der Klasse RS232Selector
mit dem Parameter RS232Selector.INTERNAL
aufgerufen werden. Die Methode onIndication()
wird von FT1_2
jedesmal aufgerufen, wenn Daten vom Power-Line-Modem (oder auch BCU, Bus Control Unit) empfangen wurden. Dabei kann es sich um eine der folgenden drei Kommunikationstypen handeln:
CF_PRM_SEND_UDAT
: Ein user datagram wurde empfangen. Dieses kann beliebige Daten enthalten, die von einer entfernten Applikation über Power-Line gesendet wurden. Der Empfang solcher UDATs ist der Normalfall und wird für den Austausch von Steuer- und Regelkommandos mit anderen Power-Line-Geräten verwendet. UDATs werden außerdem benutzt, um den Erfolg oder Misserfolg eines Kommunikationsversuchs zu quittieren.CF_PRM_REQ_STATUS
: Dies ist ein FT1.2-Statusrequest. Er sollte durch einen Aufruf der Methode sendResponse(null)
beantwortet werden.CF_PRM_REQ_CLASS1:
: Auch dies ist eine FT1.2-protokollspezifische Anfrage, die hier nicht näher erläutert werden soll. Die korrekte Antwort ist sendResponse(buf)
.
Nachdem die Voraussetzungen für die Power-Line-Kommunikation geschaffen sind, wollen wir nun ein kleines Anwendungsprogramm schreiben, das eine über Power-Line schaltbare Steckdose ein- und ausschaltet. Dies ist eine Standardapplikation in der Home Automation und kann beispielsweise zum Fernsteuern einer Lichtquelle mit JControl verwendet werden.
Der folgende Quelltext zeigt, wie auf Tastendruck ein Steuerkommando an die schaltbare Steckdose über Power-Line verschickt werden kann:
83 | /** |
84 | * Send a power-line UDAT that turns the remote plug on. |
85 | * We assume that the plug is programmed to network address 0x6000. |
86 | */ |
87 | void plugOn() { |
88 | ft12.sendUDAT(new byte[] { L_DATA_req, // link layer command |
89 | 0x0c, // priority |
90 | 0x00, 0x00, // src address |
91 | 0x60, 0x00, // dst address |
92 | (byte)0xF1, // NPCI |
93 | 0x00, // TPCI |
94 | (byte)0x81 } // command 'ON' |
95 | ); |
96 | } |
97 | |
98 | /** |
99 | * Send a power-line UDAT that turns the remote plug off. |
100 | * We assume that the plug is programmed to network address 0x6000. |
101 | */ |
102 | void plugOff() { |
103 | ft12.sendUDAT(new byte[] { L_DATA_req, // link layer command |
104 | 0x0c, // priority |
105 | 0x00, 0x00, // src address |
106 | 0x60, 0x00, // dst address |
107 | (byte)0xF1, // NPCI |
108 | 0x00, // TPCI |
109 | (byte)0x80 } // command 'OFF' |
110 | ); |
111 | } |
112 | |
113 | /** |
114 | * A simple keyboard listener. |
115 | */ |
116 | void userInterface() { |
117 | Display lcd = new Display(); |
118 | lcd.drawString("PowerLineExample", 0, 0); |
119 | lcd.drawString("Press 'UP' to turn plug on",0,20); |
120 | lcd.drawString("Press 'DOWN' to turn plug off",0,30); |
121 | |
122 | Keyboard keys = new Keyboard(); |
123 | for(;;) { |
124 | switch (keys.read()) { |
125 | case 'U': // turn plug on |
126 | plugOn(); |
127 | Buzzer.on((short)1000, (short)100); |
128 | break; |
129 | |
130 | case 'D': // turn plug off |
131 | plugOff(); |
132 | Buzzer.on((short)300, (short)100); |
133 | break; |
134 | |
135 | default: |
136 | } |
137 | } |
138 | } |
Setzt man obigen Quelltext in das Grundgerüst aus dem vorigen Abschnitt ein, ergibt sich das Programm PowerLineExample_App.java. Erzeugen Sie ein entsprechendes JControl/IDE-Projekt und laden Sie das PowerLineExample auf das JControl/PLUI. Schließen Sie zum Beispiel eine Lampe an die schaltbare Steckdose an. Stimmt die Zieladresse in dem Quelltext (hier: 0x6000
) mit der Geräte-Adresse Ihrer schaltbaren Steckdose überein, dann können Sie nun die Lampe mit JControl über Power-Line fernsteuern!