]> git.basschouten.com Git - openhab-addons.git/blob
8068157943e30c5821d97df46161712e91cc4de8
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2023 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.lghombot.internal;
14
15 import static org.openhab.binding.lghombot.internal.LGHomBotBindingConstants.*;
16
17 import java.awt.image.BufferedImage;
18 import java.io.ByteArrayOutputStream;
19 import java.io.IOException;
20 import java.time.DateTimeException;
21 import java.time.LocalDateTime;
22 import java.time.ZoneId;
23 import java.time.ZonedDateTime;
24 import java.time.format.DateTimeFormatter;
25 import java.util.concurrent.ScheduledFuture;
26 import java.util.concurrent.TimeUnit;
27
28 import javax.imageio.ImageIO;
29
30 import org.eclipse.jdt.annotation.NonNullByDefault;
31 import org.eclipse.jdt.annotation.Nullable;
32 import org.eclipse.jetty.util.UrlEncoded;
33 import org.openhab.core.io.net.http.HttpUtil;
34 import org.openhab.core.library.types.DateTimeType;
35 import org.openhab.core.library.types.DecimalType;
36 import org.openhab.core.library.types.OnOffType;
37 import org.openhab.core.library.types.RawType;
38 import org.openhab.core.library.types.StringType;
39 import org.openhab.core.thing.ChannelUID;
40 import org.openhab.core.thing.Thing;
41 import org.openhab.core.thing.ThingStatus;
42 import org.openhab.core.thing.ThingStatusDetail;
43 import org.openhab.core.thing.binding.BaseThingHandler;
44 import org.openhab.core.types.Command;
45 import org.openhab.core.types.RefreshType;
46 import org.openhab.core.types.State;
47 import org.openhab.core.types.UnDefType;
48 import org.slf4j.Logger;
49 import org.slf4j.LoggerFactory;
50
51 /**
52  * The {@link LGHomBotHandler} is responsible for handling commands, which are
53  * sent to one of the channels.
54  *
55  * @author Fredrik Ahlström - Initial contribution
56  */
57 @NonNullByDefault
58 public class LGHomBotHandler extends BaseThingHandler {
59
60     private final Logger logger = LoggerFactory.getLogger(LGHomBotHandler.class);
61
62     // This is setup in initialize().
63     private LGHomBotConfiguration config = new LGHomBotConfiguration();
64
65     private @Nullable ScheduledFuture<?> refreshTimer;
66
67     // State of HomBot
68     private String currentState = "";
69     private String currentMode = "";
70     private String currentNickname = "";
71     private String currentSrvMem = "";
72     private DecimalType currentBattery = DecimalType.ZERO;
73     private DecimalType currentCPULoad = DecimalType.ZERO;
74     private OnOffType currentCleanState = OnOffType.OFF;
75     private OnOffType currentStartState = OnOffType.OFF;
76     private OnOffType currentHomeState = OnOffType.OFF;
77     private OnOffType currentTurbo = OnOffType.OFF;
78     private OnOffType currentRepeat = OnOffType.OFF;
79     private State currentImage = UnDefType.UNDEF;
80     private State currentMap = UnDefType.UNDEF;
81     private DateTimeType currentLastClean = new DateTimeType();
82     private String currentMonday = "";
83     private String currentTuesday = "";
84     private String currentWednesday = "";
85     private String currentThursday = "";
86     private String currentFriday = "";
87     private String currentSaturday = "";
88     private String currentSunday = "";
89
90     private final DateTimeFormatter formatterLG = DateTimeFormatter.ofPattern("yyyy/MM/dd/HH/mm/ss");
91     private boolean disposed = false;
92     private boolean refreshSchedule = false;
93
94     public LGHomBotHandler(Thing thing) {
95         super(thing);
96     }
97
98     @Override
99     public void dispose() {
100         super.dispose();
101         disposed = true;
102     }
103
104     @Override
105     public void handleCommand(ChannelUID channelUID, Command command) {
106         if (command.equals(RefreshType.REFRESH)) {
107             refreshFromState(channelUID);
108         } else {
109             switch (channelUID.getId()) {
110                 case CHANNEL_CLEAN:
111                     if (command == OnOffType.ON) {
112                         if (currentState.equals(HBSTATE_HOMING)) {
113                             sendHomBotCommand("PAUSE");
114                         }
115                         sendHomBotCommand("CLEAN_START");
116                     } else if (command == OnOffType.OFF) {
117                         sendHomBotCommand("HOMING");
118                     }
119                     break;
120                 case CHANNEL_START:
121                     if (command == OnOffType.ON) {
122                         sendHomBotCommand("CLEAN_START");
123                     }
124                     break;
125                 case CHANNEL_HOME:
126                     if (command == OnOffType.ON) {
127                         sendHomBotCommand("HOMING");
128                     }
129                     break;
130                 case CHANNEL_PAUSE:
131                     if (command instanceof OnOffType) {
132                         sendHomBotCommand("PAUSE");
133                     }
134                     break;
135                 case CHANNEL_TURBO:
136                     if (command == OnOffType.ON) {
137                         sendHomBotCommand("TURBO", "true");
138                     } else if (command == OnOffType.OFF) {
139                         sendHomBotCommand("TURBO", "false");
140                     }
141                     break;
142                 case CHANNEL_REPEAT:
143                     if (command == OnOffType.ON) {
144                         sendHomBotCommand("REPEAT", "true");
145                     } else if (command == OnOffType.OFF) {
146                         sendHomBotCommand("REPEAT", "false");
147                     }
148                     break;
149                 case CHANNEL_MODE:
150                     if (command instanceof StringType) {
151                         switch (command.toString()) {
152                             case "SB":
153                                 sendHomBotCommand("CLEAN_MODE", "CLEAN_SB");
154                                 break;
155                             case "ZZ":
156                                 sendHomBotCommand("CLEAN_MODE", "CLEAN_ZZ");
157                                 break;
158                             case "SPOT":
159                                 sendHomBotCommand("CLEAN_MODE", "CLEAN_SPOT");
160                                 break;
161                             case "MACRO_SECTOR":
162                                 sendHomBotCommand("CLEAN_MODE", "CLEAN_MACRO_SECTOR");
163                                 break;
164                             default:
165                                 break;
166                         }
167                     }
168                     break;
169                 case CHANNEL_MOVE:
170                     if (command instanceof StringType) {
171                         String commandString = command.toString();
172                         switch (commandString) {
173                             case "FORWARD":
174                             case "FORWARD_LEFT":
175                             case "FORWARD_RIGHT":
176                             case "LEFT":
177                             case "RIGHT":
178                             case "BACKWARD":
179                             case "BACKWARD_LEFT":
180                             case "BACKWARD_RIGHT":
181                             case "RELEASE":
182                                 sendHomBotJoystick(commandString);
183                                 break;
184                             default:
185                                 break;
186                         }
187                     }
188                     break;
189                 default:
190                     logger.debug("Command received for unknown channel {}: {}", channelUID.getId(), command);
191                     break;
192             }
193         }
194     }
195
196     @Override
197     public void initialize() {
198         disposed = false;
199         logger.debug("Initializing handler for LG HomBot");
200         config = getConfigAs(LGHomBotConfiguration.class);
201
202         setupRefreshTimer(0);
203     }
204
205     @Override
206     public void handleRemoval() {
207         ScheduledFuture<?> localTimer = refreshTimer;
208         if (localTimer != null) {
209             localTimer.cancel(false);
210             refreshTimer = null;
211         }
212         updateStatus(ThingStatus.REMOVED);
213     }
214
215     /**
216      * Sets up a refresh timer (using the scheduler) with the given interval.
217      *
218      * @param initialWaitTime The delay before the first refresh. Maybe 0 to immediately
219      *            initiate a refresh.
220      */
221     private void setupRefreshTimer(int initialWaitTime) {
222         ScheduledFuture<?> localTimer = refreshTimer;
223         if (localTimer != null) {
224             localTimer.cancel(false);
225         }
226         refreshTimer = scheduler.scheduleWithFixedDelay(this::updateAllChannels, initialWaitTime, config.pollingPeriod,
227                 TimeUnit.SECONDS);
228     }
229
230     private String buildHttpAddress(String path) {
231         return "http://" + config.ipAddress + ":" + config.port + path;
232     }
233
234     private void sendHomBotCommand(String command) {
235         String fullCmd = "/json.cgi?" + UrlEncoded.encodeString("{\"COMMAND\":\"" + command + "\"}");
236         sendCommand(fullCmd);
237     }
238
239     private void sendHomBotCommand(String command, String argument) {
240         String fullCmd = "/json.cgi?"
241                 + UrlEncoded.encodeString("{\"COMMAND\":{\"" + command + "\":\"" + argument + "\"}}");
242         sendCommand(fullCmd);
243     }
244
245     private void sendHomBotJoystick(String command) {
246         String fullCmd = "/json.cgi?" + UrlEncoded.encodeString("{\"JOY\":\"" + command + "\"}");
247         sendCommand(fullCmd);
248     }
249
250     private @Nullable String sendCommand(String path) {
251         String url = buildHttpAddress(path);
252         logger.trace("Executing: {}", url);
253         String status = null;
254         try {
255             status = HttpUtil.executeUrl("GET", url, 1000);
256             if (getThing().getStatus() != ThingStatus.ONLINE) {
257                 updateStatus(ThingStatus.ONLINE);
258             }
259         } catch (IOException e) {
260             updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage());
261         }
262         logger.trace("Status received: {}", status);
263         return status;
264     }
265
266     private void refreshFromState(ChannelUID channelUID) {
267         switch (channelUID.getId()) {
268             case CHANNEL_STATE:
269                 updateState(channelUID, StringType.valueOf(currentState));
270                 break;
271             case CHANNEL_CLEAN:
272                 updateState(channelUID, currentCleanState);
273                 break;
274             case CHANNEL_START:
275                 updateState(channelUID, currentStartState);
276                 break;
277             case CHANNEL_HOME:
278                 updateState(channelUID, currentHomeState);
279                 break;
280             case CHANNEL_BATTERY:
281                 updateState(channelUID, currentBattery);
282                 break;
283             case CHANNEL_CPU_LOAD:
284                 updateState(channelUID, currentCPULoad);
285                 break;
286             case CHANNEL_SRV_MEM:
287                 updateState(channelUID, StringType.valueOf(currentSrvMem));
288                 break;
289             case CHANNEL_TURBO:
290                 updateState(channelUID, currentTurbo);
291                 break;
292             case CHANNEL_REPEAT:
293                 updateState(channelUID, currentRepeat);
294                 break;
295             case CHANNEL_MODE:
296                 updateState(channelUID, StringType.valueOf(currentMode));
297                 break;
298             case CHANNEL_NICKNAME:
299                 updateState(channelUID, StringType.valueOf(currentNickname));
300                 break;
301             case CHANNEL_CAMERA:
302                 parseImage();
303                 updateState(channelUID, currentImage);
304                 break;
305             case CHANNEL_LAST_CLEAN:
306                 updateState(channelUID, currentLastClean);
307                 break;
308             case CHANNEL_MAP:
309                 parseMap();
310                 updateState(channelUID, currentMap);
311                 break;
312             case CHANNEL_MONDAY:
313                 updateState(channelUID, StringType.valueOf(currentMonday));
314                 refreshSchedule = true;
315                 break;
316             case CHANNEL_TUESDAY:
317                 updateState(channelUID, StringType.valueOf(currentTuesday));
318                 refreshSchedule = true;
319                 break;
320             case CHANNEL_WEDNESDAY:
321                 updateState(channelUID, StringType.valueOf(currentWednesday));
322                 refreshSchedule = true;
323                 break;
324             case CHANNEL_THURSDAY:
325                 updateState(channelUID, StringType.valueOf(currentThursday));
326                 refreshSchedule = true;
327                 break;
328             case CHANNEL_FRIDAY:
329                 updateState(channelUID, StringType.valueOf(currentFriday));
330                 refreshSchedule = true;
331                 break;
332             case CHANNEL_SATURDAY:
333                 updateState(channelUID, StringType.valueOf(currentSaturday));
334                 refreshSchedule = true;
335                 break;
336             case CHANNEL_SUNDAY:
337                 updateState(channelUID, StringType.valueOf(currentSunday));
338                 refreshSchedule = true;
339                 break;
340             default:
341                 logger.warn("Channel refresh for {} not implemented!", channelUID.getId());
342         }
343     }
344
345     private void updateAllChannels() {
346         if (disposed) {
347             return;
348         }
349         if (refreshSchedule) {
350             refreshSchedule = false;
351             fetchSchedule();
352             return;
353         }
354
355         String status = sendCommand("/status.txt");
356         if (status != null && !status.isEmpty()) {
357             boolean parsingOk = true;
358             String[] rows = status.split("\\r?\\n");
359             for (String row : rows) {
360                 int idx = row.indexOf('=');
361                 if (idx == -1) {
362                     continue;
363                 }
364                 final String key = row.substring(0, idx);
365                 String value = row.substring(idx + 1).replace("\"", "");
366                 switch (key) {
367                     case "JSON_ROBOT_STATE":
368                         if (value.isEmpty()) {
369                             value = HBSTATE_UNKNOWN;
370                         }
371                         if (!value.equals(currentState)) {
372                             currentState = value;
373                             updateState(CHANNEL_STATE, StringType.valueOf(value));
374
375                             switch (value) {
376                                 case HBSTATE_WORKING:
377                                 case HBSTATE_BACKMOVING:
378                                 case HBSTATE_BACKMOVING_INIT:
379                                     currentCleanState = OnOffType.ON;
380                                     currentStartState = OnOffType.ON;
381                                     currentHomeState = OnOffType.OFF;
382                                     break;
383                                 case HBSTATE_HOMING:
384                                 case HBSTATE_DOCKING:
385                                     currentCleanState = OnOffType.OFF;
386                                     currentStartState = OnOffType.OFF;
387                                     currentHomeState = OnOffType.ON;
388                                     break;
389                                 default:
390                                     currentCleanState = OnOffType.OFF;
391                                     currentStartState = OnOffType.OFF;
392                                     currentHomeState = OnOffType.OFF;
393                                     break;
394                             }
395                             updateState(CHANNEL_CLEAN, currentCleanState);
396                             updateState(CHANNEL_START, currentStartState);
397                             updateState(CHANNEL_HOME, currentHomeState);
398                         }
399                         break;
400                     case "JSON_BATTPERC":
401                         try {
402                             DecimalType battery = DecimalType.valueOf(value);
403                             if (!battery.equals(currentBattery)) {
404                                 currentBattery = battery;
405                                 updateState(CHANNEL_BATTERY, battery);
406                             }
407                         } catch (NumberFormatException e) {
408                             logger.debug("Couldn't parse Battery Percent.");
409                             parsingOk = false;
410                         }
411                         break;
412                     case "CPU_IDLE":
413                         if (isLinked(CHANNEL_CPU_LOAD)) {
414                             try {
415                                 DecimalType cpuLoad = new DecimalType(100 - Double.valueOf(value).longValue());
416                                 if (!cpuLoad.equals(currentCPULoad)) {
417                                     currentCPULoad = cpuLoad;
418                                     updateState(CHANNEL_CPU_LOAD, cpuLoad);
419                                 }
420                             } catch (NumberFormatException e) {
421                                 logger.debug("Couldn't parse CPU Idle.");
422                                 parsingOk = false;
423                             }
424                         }
425                         break;
426                     case "LGSRV_MEMUSAGE":
427                         if (!value.equals(currentSrvMem)) {
428                             currentSrvMem = value;
429                             updateState(CHANNEL_SRV_MEM, StringType.valueOf(value));
430                         }
431                         break;
432                     case "JSON_TURBO":
433                         OnOffType turbo = OnOffType.from("true".equalsIgnoreCase(value));
434                         if (!turbo.equals(currentTurbo)) {
435                             currentTurbo = turbo;
436                             updateState(CHANNEL_TURBO, turbo);
437                         }
438                         break;
439                     case "JSON_REPEAT":
440                         OnOffType repeat = OnOffType.from("true".equalsIgnoreCase(value));
441                         if (!repeat.equals(currentRepeat)) {
442                             currentRepeat = repeat;
443                             updateState(CHANNEL_REPEAT, repeat);
444                         }
445                         break;
446                     case "JSON_MODE":
447                         if (!value.equals(currentMode)) {
448                             currentMode = value;
449                             updateState(CHANNEL_MODE, StringType.valueOf(value));
450                         }
451                         break;
452                     case "JSON_NICKNAME":
453                         if (!value.equals(currentNickname)) {
454                             currentNickname = value;
455                             updateState(CHANNEL_NICKNAME, StringType.valueOf(value));
456                         }
457                         break;
458                     case "CLREC_LAST_CLEAN":
459                         if (value.length() < 19) {
460                             logger.debug("Couldn't parse Last Clean from: String length: {}", value.length());
461                             parsingOk = false;
462                             break;
463                         }
464                         final String stringDate = value.substring(0, 19);
465                         try {
466                             LocalDateTime localDateTime = LocalDateTime.parse(stringDate, formatterLG);
467                             ZonedDateTime date = ZonedDateTime.of(localDateTime, ZoneId.systemDefault());
468                             DateTimeType lastClean = new DateTimeType(date);
469                             if (!lastClean.equals(currentLastClean)) {
470                                 currentLastClean = lastClean;
471                                 updateState(CHANNEL_LAST_CLEAN, lastClean);
472                             }
473                         } catch (DateTimeException e) {
474                             logger.debug("Couldn't parse Last Clean from: {}", stringDate);
475                             parsingOk = false;
476                         }
477                         break;
478                     default:
479                         break;
480                 }
481             }
482             if (!parsingOk) {
483                 logger.debug("Couldn't parse status response;\n {}", status);
484             }
485         }
486     }
487
488     private void fetchSchedule() {
489         String status = sendCommand("/.../usr/data/htdocs/timer.txt");
490
491         if (status != null && !status.isEmpty()) {
492             String monday = "";
493             String tuesday = "";
494             String wednesday = "";
495             String thursday = "";
496             String friday = "";
497             String saturday = "";
498             String sunday = "";
499             String[] rows = status.split("\\r?\\n");
500             for (String row : rows) {
501                 int idx = row.indexOf('=');
502                 String name = row.substring(0, idx);
503                 String state = row.substring(idx + 1);
504                 switch (name) {
505                     case "MONDAY":
506                         monday = state;
507                         break;
508                     case "TUESDAY":
509                         tuesday = state;
510                         break;
511                     case "WEDNESDAY":
512                         wednesday = state;
513                         break;
514                     case "THURSDAY":
515                         thursday = state;
516                         break;
517                     case "FRIDAY":
518                         friday = state;
519                         break;
520                     case "SATURDAY":
521                         saturday = state;
522                         break;
523                     case "SUNDAY":
524                         sunday = state;
525                         break;
526                     default:
527                         break;
528                 }
529
530             }
531             if (!currentMonday.equals(monday)) {
532                 currentMonday = monday;
533                 updateState(CHANNEL_MONDAY, StringType.valueOf(monday));
534             }
535             if (!currentTuesday.equals(tuesday)) {
536                 currentTuesday = tuesday;
537                 updateState(CHANNEL_TUESDAY, StringType.valueOf(tuesday));
538             }
539             if (!currentWednesday.equals(wednesday)) {
540                 currentWednesday = wednesday;
541                 updateState(CHANNEL_WEDNESDAY, StringType.valueOf(wednesday));
542             }
543             if (!currentThursday.equals(thursday)) {
544                 currentThursday = thursday;
545                 updateState(CHANNEL_THURSDAY, StringType.valueOf(thursday));
546             }
547             if (!currentFriday.equals(friday)) {
548                 currentFriday = friday;
549                 updateState(CHANNEL_FRIDAY, StringType.valueOf(friday));
550             }
551             if (!currentSaturday.equals(saturday)) {
552                 currentSaturday = saturday;
553                 updateState(CHANNEL_SATURDAY, StringType.valueOf(saturday));
554             }
555             if (!currentSunday.equals(sunday)) {
556                 currentSunday = sunday;
557                 updateState(CHANNEL_SUNDAY, StringType.valueOf(sunday));
558             }
559         }
560     }
561
562     private void parseImage() {
563         if (!isLinked(CHANNEL_CAMERA)) {
564             return;
565         }
566         final int width = 320;
567         final int height = 240;
568         final int size = width * height;
569         String url = buildHttpAddress("/images/snapshot.yuv");
570         RawType rawData = HttpUtil.downloadData(url, null, false, size * 2);
571         if (rawData != null) {
572             byte[] yuvData = rawData.getBytes();
573             currentImage = CameraUtil.parseImageFromBytes(yuvData, width, height);
574         } else {
575             logger.info("No camera image returned from HomBot.");
576         }
577     }
578
579     /** Parse the maps.html file to find the black-box filename. */
580     private String findBlackBoxFile() {
581         String url = buildHttpAddress("/sites/maps.html");
582         try {
583             String htmlString = HttpUtil.executeUrl("GET", url, 1000);
584             int idx = htmlString.indexOf("blkfiles");
585             return "/.../usr/data/blackbox/" + htmlString.substring(idx + 13, idx + 50);
586         } catch (IOException e1) {
587             updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e1.getMessage());
588         }
589         return "";
590     }
591
592     private void parseMap() {
593         if (!isLinked(CHANNEL_MAP)) {
594             return;
595         }
596         final int tileSize = 10;
597         final int tileArea = tileSize * tileSize;
598         final int rowLength = 100;
599         final int scale = 1;
600
601         String blackBox = findBlackBoxFile();
602         String url = buildHttpAddress(blackBox);
603         RawType dlData = HttpUtil.downloadData(url, null, false, -1);
604         if (dlData == null) {
605             return;
606         }
607         byte[] mapData = dlData.getBytes();
608
609         final int tileCount = mapData[32];
610         int maxX = 0;
611         int maxY = 0;
612         int minX = 0x10000;
613         int minY = 0x10000;
614         int pixPos;
615
616         for (int i = 0; i < tileCount; i++) {
617             pixPos = (mapData[52 + i * 16] & 0xFF) + (mapData[52 + 1 + i * 16] << 8);
618             int xPos = (pixPos % rowLength) * tileSize;
619             int yPos = (pixPos / rowLength) * tileSize;
620             if (xPos < minX) {
621                 minX = xPos;
622             }
623             if (xPos > maxX) {
624                 maxX = xPos;
625             }
626             if (yPos > maxY) {
627                 maxY = yPos;
628             }
629             if (yPos < minY) {
630                 minY = yPos;
631             }
632         }
633
634         final int width = (tileSize + maxX - minX) * scale;
635         final int height = (tileSize + maxY - minY) * scale;
636
637         BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
638         for (int i = 0; i < height; i++) {
639             for (int j = 0; j < width; j++) {
640                 image.setRGB(j, i, 0xFFFFFF);
641             }
642         }
643         for (int i = 0; i < tileCount; i++) {
644             pixPos = (mapData[52 + i * 16] & 0xFF) + (mapData[52 + 1 + i * 16] << 8);
645             int xPos = ((pixPos % rowLength) * tileSize - minX) * scale;
646             int yPos = (maxY - (pixPos / rowLength) * tileSize) * scale;
647             int indexTab = 16044 + i * tileArea;
648             for (int j = 0; j < tileSize; j++) {
649                 for (int k = 0; k < tileSize; k++) {
650                     int p = 0xFFFFFF;
651                     if ((mapData[indexTab] & 0xF0) != 0) {
652                         p = 0xFF0000;
653                     } else if (mapData[indexTab] != 0) {
654                         p = 0xBFBFBF;
655                     }
656                     image.setRGB(xPos + k * scale, yPos + (9 - j) * scale, p);
657                     indexTab++;
658                 }
659             }
660         }
661
662         ByteArrayOutputStream baos = new ByteArrayOutputStream();
663         try {
664             if (!ImageIO.write(image, "png", baos)) {
665                 logger.debug("Couldn't find PNG writer.");
666             }
667         } catch (IOException e) {
668             logger.info("IOException creating PNG image.", e);
669         }
670         byte[] byteArray = baos.toByteArray();
671         if (byteArray != null && byteArray.length > 0) {
672             currentMap = new RawType(byteArray, "image/png");
673         } else {
674             currentMap = UnDefType.UNDEF;
675         }
676     }
677 }