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