]> git.basschouten.com Git - openhab-addons.git/blob
8125ba8a2c185946b2d70f6675f73746bc109c9b
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2020 Contributors to the openHAB project
3  *
4  * See the NOTICE file(s) distributed with this work for additional
5  * information.
6  *
7  * This program and the accompanying materials are made available under the
8  * terms of the Eclipse Public License 2.0 which is available at
9  * http://www.eclipse.org/legal/epl-2.0
10  *
11  * SPDX-License-Identifier: EPL-2.0
12  */
13 package org.openhab.binding.velbus.internal.discovery;
14
15 import static org.openhab.binding.velbus.internal.VelbusBindingConstants.*;
16
17 import java.util.Arrays;
18 import java.util.Date;
19 import java.util.HashMap;
20 import java.util.Map;
21
22 import org.eclipse.jdt.annotation.NonNullByDefault;
23 import org.eclipse.jdt.annotation.Nullable;
24 import org.openhab.binding.velbus.internal.VelbusChannelIdentifier;
25 import org.openhab.binding.velbus.internal.VelbusFirstGenerationDeviceModuleAddress;
26 import org.openhab.binding.velbus.internal.VelbusModule;
27 import org.openhab.binding.velbus.internal.VelbusModuleAddress;
28 import org.openhab.binding.velbus.internal.VelbusPacketListener;
29 import org.openhab.binding.velbus.internal.handler.VelbusBridgeHandler;
30 import org.openhab.binding.velbus.internal.packets.VelbusPacket;
31 import org.openhab.binding.velbus.internal.packets.VelbusScanPacket;
32 import org.openhab.core.config.discovery.AbstractDiscoveryService;
33 import org.openhab.core.config.discovery.DiscoveryResult;
34 import org.openhab.core.config.discovery.DiscoveryResultBuilder;
35 import org.openhab.core.config.discovery.DiscoveryService;
36 import org.openhab.core.thing.ThingUID;
37 import org.openhab.core.thing.binding.ThingHandler;
38 import org.openhab.core.thing.binding.ThingHandlerService;
39 import org.slf4j.Logger;
40 import org.slf4j.LoggerFactory;
41
42 /**
43  * If the user scans manually for things this
44  * {@link VelbusThingDiscoveryService}
45  * is used to return Velbus Modules as things to the framework.
46  *
47  * @author Cedric Boon - Initial contribution
48  */
49 @NonNullByDefault
50 public class VelbusThingDiscoveryService extends AbstractDiscoveryService
51         implements DiscoveryService, ThingHandlerService, VelbusPacketListener {
52     private static final int SEARCH_TIME = 60;
53
54     private final Logger logger = LoggerFactory.getLogger(VelbusThingDiscoveryService.class);
55
56     private Map<Byte, VelbusModule> velbusModules = new HashMap<>();
57
58     private @Nullable VelbusBridgeHandler velbusBridgeHandler;
59
60     public VelbusThingDiscoveryService() {
61         super(SUPPORTED_THING_TYPES_UIDS, SEARCH_TIME);
62     }
63
64     @Override
65     public void deactivate() {
66         removeOlderResults(new Date().getTime());
67
68         final VelbusBridgeHandler velbusBridgeHandler = this.velbusBridgeHandler;
69         if (velbusBridgeHandler != null) {
70             velbusBridgeHandler.clearDefaultPacketListener();
71         }
72     }
73
74     @Override
75     protected void startScan() {
76         for (int i = 0x00; i <= 0xFF; i++) {
77             VelbusScanPacket packet = new VelbusScanPacket((byte) i);
78             byte[] packetBytes = packet.getBytes();
79
80             final VelbusBridgeHandler velbusBridgeHandler = this.velbusBridgeHandler;
81             if (velbusBridgeHandler != null) {
82                 velbusBridgeHandler.sendPacket(packetBytes);
83             }
84         }
85     }
86
87     @Override
88     public void onPacketReceived(byte[] packet) {
89         if (packet[0] == VelbusPacket.STX && packet.length >= 5) {
90             byte address = packet[2];
91             byte length = packet[3];
92             byte command = packet[4];
93
94             if (command == COMMAND_MODULE_TYPE && packet.length >= 10) {
95                 handleModuleTypeCommand(packet, address);
96             } else if (command == COMMAND_MODULE_NAME_PART1 & packet.length >= 4 + length) {
97                 handleChannelNameCommand(packet, address, length, 1);
98             } else if (command == COMMAND_MODULE_NAME_PART2 && packet.length >= 4 + length) {
99                 handleChannelNameCommand(packet, address, length, 2);
100             } else if (command == COMMAND_MODULE_NAME_PART3 && packet.length >= 4 + length) {
101                 handleChannelNameCommand(packet, address, length, 3);
102             } else if (command == COMMAND_SUBTYPE && packet.length >= 4 + length) {
103                 handleModuleSubtypeCommand(packet, address);
104             } else {
105                 logger.debug("Unknown command '{}' to address '{}'.", String.format("%02X", command),
106                         String.format("%02X", address));
107             }
108         }
109     }
110
111     private void handleModuleTypeCommand(byte[] packet, byte address) {
112         byte moduleType = packet[5];
113         byte highByteOfSerialNumber = packet[6];
114         byte lowByteOfSerialNumber = packet[7];
115         byte memoryMapVersion = packet[8];
116         byte buildYear = packet[9];
117         byte buildWeek = packet[10];
118
119         VelbusModule velbusModule = null;
120         switch (moduleType) {
121             case MODULE_TYPE_VMB1BL:
122                 velbusModule = new VelbusModule(new VelbusFirstGenerationDeviceModuleAddress(address), moduleType,
123                         highByteOfSerialNumber, lowByteOfSerialNumber, memoryMapVersion, buildYear, buildWeek,
124                         THING_TYPE_VMB1BL, 1);
125                 break;
126             case MODULE_TYPE_VMB1BLS:
127                 velbusModule = new VelbusModule(new VelbusModuleAddress(address, 0), moduleType, highByteOfSerialNumber,
128                         lowByteOfSerialNumber, memoryMapVersion, buildYear, buildWeek, THING_TYPE_VMB1BLS, 1);
129                 break;
130             case MODULE_TYPE_VMB1DM:
131                 velbusModule = new VelbusModule(new VelbusModuleAddress(address, 0), moduleType, highByteOfSerialNumber,
132                         lowByteOfSerialNumber, memoryMapVersion, buildYear, buildWeek, THING_TYPE_VMB1DM, 1);
133                 break;
134             case MODULE_TYPE_VMB1LED:
135                 velbusModule = new VelbusModule(new VelbusModuleAddress(address, 0), moduleType, highByteOfSerialNumber,
136                         lowByteOfSerialNumber, memoryMapVersion, buildYear, buildWeek, THING_TYPE_VMB1LED, 1);
137                 break;
138             case MODULE_TYPE_VMB1RY:
139                 velbusModule = new VelbusModule(new VelbusModuleAddress(address, 0), moduleType, highByteOfSerialNumber,
140                         lowByteOfSerialNumber, memoryMapVersion, buildYear, buildWeek, THING_TYPE_VMB1RY, 1);
141                 break;
142             case MODULE_TYPE_VMB1RYNO:
143                 velbusModule = new VelbusModule(new VelbusModuleAddress(address, 0), moduleType, highByteOfSerialNumber,
144                         lowByteOfSerialNumber, memoryMapVersion, buildYear, buildWeek, THING_TYPE_VMB1RYNO, 5);
145                 break;
146             case MODULE_TYPE_VMB1RYNOS:
147                 velbusModule = new VelbusModule(new VelbusModuleAddress(address, 0), moduleType, highByteOfSerialNumber,
148                         lowByteOfSerialNumber, memoryMapVersion, buildYear, buildWeek, THING_TYPE_VMB1RYNOS, 5);
149                 break;
150             case MODULE_TYPE_VMB1RYS:
151                 velbusModule = new VelbusModule(new VelbusModuleAddress(address, 0), moduleType, highByteOfSerialNumber,
152                         lowByteOfSerialNumber, memoryMapVersion, buildYear, buildWeek, THING_TYPE_VMB1RYS, 5);
153                 break;
154             case MODULE_TYPE_VMB1TS:
155                 velbusModule = new VelbusModule(new VelbusModuleAddress(address, 0), moduleType, highByteOfSerialNumber,
156                         lowByteOfSerialNumber, memoryMapVersion, buildYear, buildWeek, THING_TYPE_VMB1TS, 1);
157                 break;
158             case MODULE_TYPE_VMB2BL:
159                 velbusModule = new VelbusModule(new VelbusFirstGenerationDeviceModuleAddress(address), moduleType,
160                         highByteOfSerialNumber, lowByteOfSerialNumber, memoryMapVersion, buildYear, buildWeek,
161                         THING_TYPE_VMB2BL, 2);
162                 break;
163             case MODULE_TYPE_VMB2BLE:
164                 velbusModule = new VelbusModule(new VelbusModuleAddress(address, 0), moduleType, highByteOfSerialNumber,
165                         lowByteOfSerialNumber, memoryMapVersion, buildYear, buildWeek, THING_TYPE_VMB2BLE, 2);
166                 break;
167             case MODULE_TYPE_VMB2PBN:
168                 velbusModule = new VelbusModule(new VelbusModuleAddress(address, 0), moduleType, highByteOfSerialNumber,
169                         lowByteOfSerialNumber, memoryMapVersion, buildYear, buildWeek, THING_TYPE_VMB2PBN, 8);
170                 break;
171             case MODULE_TYPE_VMB4AN:
172                 velbusModule = new VelbusModule(new VelbusModuleAddress(address, 0), moduleType, highByteOfSerialNumber,
173                         lowByteOfSerialNumber, memoryMapVersion, buildYear, buildWeek, THING_TYPE_VMB4AN, 4);
174                 break;
175             case MODULE_TYPE_VMB4DC:
176                 velbusModule = new VelbusModule(new VelbusModuleAddress(address, 0), moduleType, highByteOfSerialNumber,
177                         lowByteOfSerialNumber, memoryMapVersion, buildYear, buildWeek, THING_TYPE_VMB4DC, 4);
178                 break;
179             case MODULE_TYPE_VMB4RY:
180                 velbusModule = new VelbusModule(new VelbusModuleAddress(address, 0), moduleType, highByteOfSerialNumber,
181                         lowByteOfSerialNumber, memoryMapVersion, buildYear, buildWeek, THING_TYPE_VMB4RY, 4);
182                 break;
183             case MODULE_TYPE_VMB4RYLD:
184                 velbusModule = new VelbusModule(new VelbusModuleAddress(address, 0), moduleType, highByteOfSerialNumber,
185                         lowByteOfSerialNumber, memoryMapVersion, buildYear, buildWeek, THING_TYPE_VMB4RYLD, 5);
186                 break;
187             case MODULE_TYPE_VMB4RYNO:
188                 velbusModule = new VelbusModule(new VelbusModuleAddress(address, 0), moduleType, highByteOfSerialNumber,
189                         lowByteOfSerialNumber, memoryMapVersion, buildYear, buildWeek, THING_TYPE_VMB4RYNO, 5);
190                 break;
191             case MODULE_TYPE_VMB6IN:
192                 velbusModule = new VelbusModule(new VelbusModuleAddress(address, 0), moduleType, highByteOfSerialNumber,
193                         lowByteOfSerialNumber, memoryMapVersion, buildYear, buildWeek, THING_TYPE_VMB6IN, 6);
194                 break;
195             case MODULE_TYPE_VMB6PBN:
196                 velbusModule = new VelbusModule(new VelbusModuleAddress(address, 0), moduleType, highByteOfSerialNumber,
197                         lowByteOfSerialNumber, memoryMapVersion, buildYear, buildWeek, THING_TYPE_VMB6PBN, 8);
198                 break;
199             case MODULE_TYPE_VMB7IN:
200                 velbusModule = new VelbusModule(new VelbusModuleAddress(address, 0), moduleType, highByteOfSerialNumber,
201                         lowByteOfSerialNumber, memoryMapVersion, buildYear, buildWeek, THING_TYPE_VMB7IN, 8);
202                 break;
203             case MODULE_TYPE_VMB8IR:
204                 velbusModule = new VelbusModule(new VelbusModuleAddress(address, 0), moduleType, highByteOfSerialNumber,
205                         lowByteOfSerialNumber, memoryMapVersion, buildYear, buildWeek, THING_TYPE_VMB8IR, 8);
206                 break;
207             case MODULE_TYPE_VMB8PB:
208                 velbusModule = new VelbusModule(new VelbusModuleAddress(address, 0), moduleType, highByteOfSerialNumber,
209                         lowByteOfSerialNumber, memoryMapVersion, buildYear, buildWeek, THING_TYPE_VMB8PB, 8);
210                 break;
211             case MODULE_TYPE_VMB8PBU:
212                 velbusModule = new VelbusModule(new VelbusModuleAddress(address, 0), moduleType, highByteOfSerialNumber,
213                         lowByteOfSerialNumber, memoryMapVersion, buildYear, buildWeek, THING_TYPE_VMB8PBU, 8);
214                 break;
215             case MODULE_TYPE_VMBDME:
216                 velbusModule = new VelbusModule(new VelbusModuleAddress(address, 0), moduleType, highByteOfSerialNumber,
217                         lowByteOfSerialNumber, memoryMapVersion, buildYear, buildWeek, THING_TYPE_VMBDME, 1);
218                 break;
219             case MODULE_TYPE_VMBDMI:
220                 velbusModule = new VelbusModule(new VelbusModuleAddress(address, 0), moduleType, highByteOfSerialNumber,
221                         lowByteOfSerialNumber, memoryMapVersion, buildYear, buildWeek, THING_TYPE_VMBDMI, 1);
222                 break;
223             case MODULE_TYPE_VMBDMIR:
224                 velbusModule = new VelbusModule(new VelbusModuleAddress(address, 0), moduleType, highByteOfSerialNumber,
225                         lowByteOfSerialNumber, memoryMapVersion, buildYear, buildWeek, THING_TYPE_VMBDMIR, 1);
226                 break;
227             case MODULE_TYPE_VMBEL1:
228                 velbusModule = new VelbusModule(new VelbusModuleAddress(address, 4), moduleType, highByteOfSerialNumber,
229                         lowByteOfSerialNumber, memoryMapVersion, buildYear, buildWeek, THING_TYPE_VMBEL1, 9);
230                 break;
231             case MODULE_TYPE_VMBEL2:
232                 velbusModule = new VelbusModule(new VelbusModuleAddress(address, 4), moduleType, highByteOfSerialNumber,
233                         lowByteOfSerialNumber, memoryMapVersion, buildYear, buildWeek, THING_TYPE_VMBEL2, 9);
234                 break;
235             case MODULE_TYPE_VMBEL4:
236                 velbusModule = new VelbusModule(new VelbusModuleAddress(address, 4), moduleType, highByteOfSerialNumber,
237                         lowByteOfSerialNumber, memoryMapVersion, buildYear, buildWeek, THING_TYPE_VMBEL4, 9);
238                 break;
239             case MODULE_TYPE_VMBELO:
240                 velbusModule = new VelbusModule(new VelbusModuleAddress(address, 4), moduleType, highByteOfSerialNumber,
241                         lowByteOfSerialNumber, memoryMapVersion, buildYear, buildWeek, THING_TYPE_VMBELO, 33);
242                 break;
243             case MODULE_TYPE_VMBGP1:
244                 velbusModule = new VelbusModule(new VelbusModuleAddress(address, 4), moduleType, highByteOfSerialNumber,
245                         lowByteOfSerialNumber, memoryMapVersion, buildYear, buildWeek, THING_TYPE_VMBGP1, 9);
246                 break;
247             case MODULE_TYPE_VMBGP1_2:
248                 velbusModule = new VelbusModule(new VelbusModuleAddress(address, 4), moduleType, highByteOfSerialNumber,
249                         lowByteOfSerialNumber, memoryMapVersion, buildYear, buildWeek, THING_TYPE_VMBGP1_2, 9);
250                 break;
251             case MODULE_TYPE_VMBGP2:
252                 velbusModule = new VelbusModule(new VelbusModuleAddress(address, 4), moduleType, highByteOfSerialNumber,
253                         lowByteOfSerialNumber, memoryMapVersion, buildYear, buildWeek, THING_TYPE_VMBGP2, 9);
254                 break;
255             case MODULE_TYPE_VMBGP2_2:
256                 velbusModule = new VelbusModule(new VelbusModuleAddress(address, 4), moduleType, highByteOfSerialNumber,
257                         lowByteOfSerialNumber, memoryMapVersion, buildYear, buildWeek, THING_TYPE_VMBGP2_2, 9);
258                 break;
259             case MODULE_TYPE_VMBGP4:
260                 velbusModule = new VelbusModule(new VelbusModuleAddress(address, 4), moduleType, highByteOfSerialNumber,
261                         lowByteOfSerialNumber, memoryMapVersion, buildYear, buildWeek, THING_TYPE_VMBGP4, 9);
262                 break;
263             case MODULE_TYPE_VMBGP4_2:
264                 velbusModule = new VelbusModule(new VelbusModuleAddress(address, 4), moduleType, highByteOfSerialNumber,
265                         lowByteOfSerialNumber, memoryMapVersion, buildYear, buildWeek, THING_TYPE_VMBGP4_2, 9);
266                 break;
267             case MODULE_TYPE_VMBGP4PIR:
268                 velbusModule = new VelbusModule(new VelbusModuleAddress(address, 4), moduleType, highByteOfSerialNumber,
269                         lowByteOfSerialNumber, memoryMapVersion, buildYear, buildWeek, THING_TYPE_VMBGP4PIR, 9);
270                 break;
271             case MODULE_TYPE_VMBGP4PIR_2:
272                 velbusModule = new VelbusModule(new VelbusModuleAddress(address, 4), moduleType, highByteOfSerialNumber,
273                         lowByteOfSerialNumber, memoryMapVersion, buildYear, buildWeek, THING_TYPE_VMBGP4PIR_2, 9);
274                 break;
275             case MODULE_TYPE_VMBGPO:
276                 velbusModule = new VelbusModule(new VelbusModuleAddress(address, 4), moduleType, highByteOfSerialNumber,
277                         lowByteOfSerialNumber, memoryMapVersion, buildYear, buildWeek, THING_TYPE_VMBGPO, 33);
278                 break;
279             case MODULE_TYPE_VMBGPOD:
280                 velbusModule = new VelbusModule(new VelbusModuleAddress(address, 4), moduleType, highByteOfSerialNumber,
281                         lowByteOfSerialNumber, memoryMapVersion, buildYear, buildWeek, THING_TYPE_VMBGPOD, 33);
282                 break;
283             case MODULE_TYPE_VMBGPOD_2:
284                 velbusModule = new VelbusModule(new VelbusModuleAddress(address, 4), moduleType, highByteOfSerialNumber,
285                         lowByteOfSerialNumber, memoryMapVersion, buildYear, buildWeek, THING_TYPE_VMBGPOD_2, 33);
286                 break;
287             case MODULE_TYPE_VMBMETEO:
288                 velbusModule = new VelbusModule(new VelbusModuleAddress(address, 0), moduleType, highByteOfSerialNumber,
289                         lowByteOfSerialNumber, memoryMapVersion, buildYear, buildWeek, THING_TYPE_VMBMETEO, 13);
290                 break;
291             case MODULE_TYPE_VMBPIRC:
292                 velbusModule = new VelbusModule(new VelbusModuleAddress(address, 0), moduleType, highByteOfSerialNumber,
293                         lowByteOfSerialNumber, memoryMapVersion, buildYear, buildWeek, THING_TYPE_VMBPIRC, 7);
294                 break;
295             case MODULE_TYPE_VMBPIRM:
296                 velbusModule = new VelbusModule(new VelbusModuleAddress(address, 0), moduleType, highByteOfSerialNumber,
297                         lowByteOfSerialNumber, memoryMapVersion, buildYear, buildWeek, THING_TYPE_VMBPIRM, 7);
298                 break;
299             case MODULE_TYPE_VMBPIRO:
300                 velbusModule = new VelbusModule(new VelbusModuleAddress(address, 0), moduleType, highByteOfSerialNumber,
301                         lowByteOfSerialNumber, memoryMapVersion, buildYear, buildWeek, THING_TYPE_VMBPIRO, 9);
302                 break;
303             case MODULE_TYPE_VMBRFR8S:
304                 velbusModule = new VelbusModule(new VelbusModuleAddress(address, 0), moduleType, highByteOfSerialNumber,
305                         lowByteOfSerialNumber, memoryMapVersion, buildYear, buildWeek, THING_TYPE_VMBRFR8S, 8);
306                 break;
307         }
308
309         if (velbusModule != null) {
310             registerVelbusModule(address, velbusModule);
311         }
312     }
313
314     private void handleModuleSubtypeCommand(byte[] packet, byte address) {
315         if (velbusModules.containsKey(address)) {
316             VelbusModule velbusModule = velbusModules.get(address);
317
318             byte[] subAddresses = new byte[4];
319             System.arraycopy(packet, 8, subAddresses, 0, 4);
320
321             velbusModule.getModuleAddress().setSubAddresses(subAddresses);
322
323             for (int i = 0; i < subAddresses.length; i++) {
324                 if (subAddresses[i] != (byte) 0xFF) {
325                     velbusModules.put(subAddresses[i], velbusModule);
326                 }
327             }
328
329             notifyDiscoveredVelbusModule(velbusModule);
330         }
331     }
332
333     protected void registerVelbusModule(byte address, VelbusModule velbusModule) {
334         velbusModules.put(address, velbusModule);
335         notifyDiscoveredVelbusModule(velbusModule);
336         velbusModule.sendChannelNameRequests(velbusBridgeHandler);
337     }
338
339     private void handleChannelNameCommand(byte[] packet, byte address, byte length, int namePartNumber) {
340         if (velbusModules.containsKey(address)) {
341             VelbusModule velbusModule = velbusModules.get(address);
342
343             byte channel = packet[5];
344             byte[] namePart = Arrays.copyOfRange(packet, 6, 6 + length - 2);
345
346             VelbusChannelIdentifier velbusChannelIdentifier = new VelbusChannelIdentifier(address, channel);
347             velbusModule.setChannelName(velbusChannelIdentifier, namePartNumber, namePart);
348             notifyDiscoveredVelbusModule(velbusModule);
349         }
350     }
351
352     private void notifyDiscoveredVelbusModule(VelbusModule velbusModule) {
353         final VelbusBridgeHandler velbusBridgeHandler = this.velbusBridgeHandler;
354         if (velbusBridgeHandler != null) {
355             ThingUID bridgeUID = velbusBridgeHandler.getThing().getUID();
356
357             DiscoveryResult discoveryResult = DiscoveryResultBuilder.create(velbusModule.getThingUID(bridgeUID))
358                     .withThingType(velbusModule.getThingTypeUID()).withProperties(velbusModule.getProperties())
359                     .withRepresentationProperty(ADDRESS).withBridge(bridgeUID).withLabel(velbusModule.getLabel())
360                     .build();
361
362             thingDiscovered(discoveryResult);
363         }
364     }
365
366     @Override
367     public void setThingHandler(@Nullable ThingHandler handler) {
368         if (handler instanceof VelbusBridgeHandler) {
369             final VelbusBridgeHandler velbusBridgeHandler = (VelbusBridgeHandler) handler;
370             this.velbusBridgeHandler = velbusBridgeHandler;
371             velbusBridgeHandler.setDefaultPacketListener(this);
372         }
373     }
374
375     @Override
376     public @Nullable ThingHandler getThingHandler() {
377         return this.velbusBridgeHandler;
378     }
379 }