/**
 * Copyright (c) 2010-2020 Contributors to the openHAB project
 *
 * See the NOTICE file(s) distributed with this work for additional
 * information.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0
 *
 * SPDX-License-Identifier: EPL-2.0
 */

 /* ***********************************************************
 * This file was automatically generated on 2022-01-03.      *
 *                                                           *
 * openHAB Bindings Version 2.0.0                            *
 *                                                           *
 * If you have a bugfix for this file and want to commit it, *
 * please fix the bug in the generator. You can find a link  *
 * to the generators git repository on tinkerforge.com       *
 *************************************************************/

package org.openhab.binding.tinkerforge.internal.device;

import java.net.URI;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import org.eclipse.smarthome.config.core.Configuration;
import org.eclipse.smarthome.config.core.ConfigDescription;
import org.eclipse.smarthome.config.core.ConfigDescriptionBuilder;
import org.eclipse.smarthome.config.core.ConfigDescriptionParameter.Type;
import org.eclipse.smarthome.config.core.ConfigDescriptionParameterBuilder;
import org.eclipse.smarthome.config.core.ConfigDescriptionParameterGroup;
import org.eclipse.smarthome.config.core.ParameterOption;
import org.eclipse.smarthome.core.types.State;
import org.eclipse.smarthome.core.types.StateOption;
import org.eclipse.smarthome.core.types.Command;
import org.eclipse.smarthome.core.types.CommandDescriptionBuilder;
import org.eclipse.smarthome.core.types.CommandOption;
import org.eclipse.smarthome.core.thing.ChannelUID;
import org.eclipse.smarthome.core.thing.ThingStatus;
import org.eclipse.smarthome.core.thing.ThingTypeUID;
import org.eclipse.smarthome.core.thing.binding.BaseThingHandler;
import org.eclipse.smarthome.core.thing.type.ChannelDefinitionBuilder;
import org.eclipse.smarthome.core.thing.type.ChannelType;
import org.eclipse.smarthome.core.thing.type.ChannelTypeBuilder;
import org.eclipse.smarthome.core.thing.type.ChannelTypeUID;
import org.eclipse.smarthome.core.types.RefreshType;
import org.eclipse.smarthome.core.thing.type.ThingType;
import org.eclipse.smarthome.core.thing.type.ThingTypeBuilder;
import org.eclipse.smarthome.core.types.StateDescriptionFragmentBuilder;
import org.openhab.binding.tinkerforge.internal.TinkerforgeBindingConstants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.eclipse.smarthome.core.library.types.DecimalType;
import org.eclipse.smarthome.core.library.types.QuantityType;
import org.eclipse.smarthome.core.library.unit.MetricPrefix;
import org.eclipse.smarthome.core.library.unit.SIUnits;
import org.eclipse.smarthome.core.library.unit.SmartHomeUnits;
import org.eclipse.smarthome.core.thing.CommonTriggerEvents;
import org.eclipse.smarthome.core.library.types.StringType;
import org.eclipse.smarthome.core.library.types.PointType;
import org.eclipse.smarthome.core.library.types.DateTimeType;
import org.eclipse.smarthome.core.library.types.OpenClosedType;
import java.time.ZoneId;

import com.tinkerforge.BrickletGPSV2;
import com.tinkerforge.IPConnection;
import com.tinkerforge.TinkerforgeException;

import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;

/**
 * Wraps the Java Bindings of the GPS Bricklet 2.0.
 * @author Erik Fleckstein - Initial contribution
 */
@NonNullByDefault
public class BrickletGPSV2Wrapper extends BrickletGPSV2 implements CoMCUFlashable, DeviceWrapper {
    public static final DeviceInfo DEVICE_INFO = new DeviceInfo(BrickletGPSV2.DEVICE_DISPLAY_NAME, "brickletgpsv2", BrickletGPSV2.DEVICE_IDENTIFIER, BrickletGPSV2Wrapper.class, BrickletGPSV2Actions.class, "2.0.2", true);

    public BrickletGPSV2Wrapper(String uid, IPConnection ipcon) {
        super(uid, ipcon);
    }

    private List<ScheduledFuture<?>> manualChannelUpdates = new ArrayList<>();
    private List<ListenerReg<?>> listenerRegs = new ArrayList<>();

    public void cancelManualUpdates() {
        manualChannelUpdates.forEach(f -> f.cancel(true));
    }

    public <T> T reg(T listener, Consumer<T> toRemove) {
        listenerRegs.add(new ListenerReg<T>(listener, toRemove));
        return listener;
    }

    
    private final Logger logger = LoggerFactory.getLogger(BrickletGPSV2Wrapper.class);

    @Override
    public void initialize(org.eclipse.smarthome.config.core.Configuration config, Function<String, org.eclipse.smarthome.config.core.Configuration> getChannelConfigFn, BiConsumer<String, org.eclipse.smarthome.core.types.State> updateStateFn, BiConsumer<String, String> triggerChannelFn, ScheduledExecutorService scheduler, BaseThingHandler handler) throws TinkerforgeException {
        this.setResponseExpectedAll(true);
        BrickletGPSV2Config cfg = (BrickletGPSV2Config) config.as(BrickletGPSV2Config.class);
        this.addCoordinatesListener(this.reg((latitude, ns, longitude, ew) -> {if(true) {updateStateFn.accept("BrickletGPSV2Location", transformBrickletGPSV2LocationCallback0(latitude, ns, longitude, ew, cfg));}}, this::removeCoordinatesListener));
		this.addStatusListener(this.reg((hasFix, satellitesView) -> {if(true) {updateStateFn.accept("BrickletGPSV2Fix", transformBrickletGPSV2FixCallback0(hasFix, satellitesView, cfg));}}, this::removeStatusListener));
		this.addStatusListener(this.reg((hasFix, satellitesView) -> {if(true) {updateStateFn.accept("BrickletGPSV2SatellitesInView", transformBrickletGPSV2SatellitesInViewCallback0(hasFix, satellitesView, cfg));}}, this::removeStatusListener));
		this.addAltitudeListener(this.reg((altitude, geoidalSeparation) -> {if(true) {updateStateFn.accept("BrickletGPSV2Altitude", transformBrickletGPSV2AltitudeCallback0(altitude, geoidalSeparation, cfg));}}, this::removeAltitudeListener));
		this.addAltitudeListener(this.reg((altitude, geoidalSeparation) -> {if(true) {updateStateFn.accept("BrickletGPSV2GeoidalSeparation", transformBrickletGPSV2GeoidalSeparationCallback0(altitude, geoidalSeparation, cfg));}}, this::removeAltitudeListener));
		this.addMotionListener(this.reg((course, speed) -> {if(true) {updateStateFn.accept("BrickletGPSV2Course", transformBrickletGPSV2CourseCallback0(course, speed, cfg));}}, this::removeMotionListener));
		this.addMotionListener(this.reg((course, speed) -> {if(true) {updateStateFn.accept("BrickletGPSV2Speed", transformBrickletGPSV2SpeedCallback0(course, speed, cfg));}}, this::removeMotionListener));
		this.addDateTimeListener(this.reg((date, time) -> {if(true) {updateStateFn.accept("BrickletGPSV2DateTime", transformBrickletGPSV2DateTimeCallback0(date, time, cfg));}}, this::removeDateTimeListener));
		this.addPulsePerSecondListener(this.reg(() -> {if(true) {triggerChannelFn.accept("BrickletGPSV2PulsePerSecond", transformBrickletGPSV2PulsePerSecondCallback0(cfg));}}, this::removePulsePerSecondListener));
        this.setFixLEDConfig(cfg.fixLEDConfig);
		        this.setSBASConfig(cfg.enableSBAS ? 0 : 1);
		        this.setStatusCallbackPeriod(cfg.statusUpdateInterval);
		        this.setAltitudeCallbackPeriod(cfg.altitudeUpdateInterval);
		        this.setMotionCallbackPeriod(cfg.motionUpdateInterval);
		this.setStatusLEDConfig(cfg.statusLEDConfig);
		{
		BrickletGPSV2CoordinatesConfig channelCfg = getChannelConfigFn.apply("BrickletGPSV2Location").as(BrickletGPSV2CoordinatesConfig.class);
		this.setCoordinatesCallbackPeriod(channelCfg.updateInterval);
		}
		{
		BrickletGPSV2DateTimeConfig channelCfg = getChannelConfigFn.apply("BrickletGPSV2DateTime").as(BrickletGPSV2DateTimeConfig.class);
		this.setDateTimeCallbackPeriod(channelCfg.updateInterval);
		}
    }

    @Override
    public void dispose(org.eclipse.smarthome.config.core.Configuration config) throws TinkerforgeException {
        listenerRegs.forEach(ListenerReg::deregister);

        
        this.setCoordinatesCallbackPeriod(0);
		this.setDateTimeCallbackPeriod(0);
		this.setStatusCallbackPeriod(0);
		        this.setAltitudeCallbackPeriod(0);
		        this.setMotionCallbackPeriod(0);
    }

    @Override
    public List<String> getEnabledChannels(org.eclipse.smarthome.config.core.Configuration config) throws TinkerforgeException{
        List<String> result = new ArrayList<String>();
        result.add("BrickletGPSV2Location");
		result.add("BrickletGPSV2Fix");
		result.add("BrickletGPSV2SatellitesInView");
		result.add("BrickletGPSV2Altitude");
		result.add("BrickletGPSV2GeoidalSeparation");
		result.add("BrickletGPSV2Course");
		result.add("BrickletGPSV2Speed");
		result.add("BrickletGPSV2DateTime");
		result.add("BrickletGPSV2PulsePerSecond");
		result.add("BrickletGPSV2Restart");
        return result;
    }

    public static @Nullable ChannelType getChannelType(ChannelTypeUID channelTypeUID) {
        switch(channelTypeUID.getId()) {
            case "BrickletGPSV2Coordinates":
                return ChannelTypeBuilder.state(new ChannelTypeUID("tinkerforge", "BrickletGPSV2Coordinates"), "Location", "Location").withConfigDescriptionURI(URI.create("channel-type:tinkerforge:BrickletGPSV2Coordinates")).withDescription("The location as determined by the bricklet.").build();
            case "BrickletGPSV2Fix":
                return ChannelTypeBuilder.state(new ChannelTypeUID("tinkerforge", "BrickletGPSV2Fix"), "Fix", "Contact").withConfigDescriptionURI(URI.create("channel-type:tinkerforge:BrickletGPSV2Fix")).withDescription("The current fix status").build();
            case "BrickletGPSV2SatellitesInView":
                return ChannelTypeBuilder.state(new ChannelTypeUID("tinkerforge", "BrickletGPSV2SatellitesInView"), "Satellites In View", "Number:Dimensionless").withConfigDescriptionURI(URI.create("channel-type:tinkerforge:BrickletGPSV2SatellitesInView")).withDescription("The number of satellites that are in view.")
.withStateDescription(StateDescriptionFragmentBuilder.create().withPattern("%d").withReadOnly(true).build().toStateDescription()).build();
            case "BrickletGPSV2Altitude":
                return ChannelTypeBuilder.state(new ChannelTypeUID("tinkerforge", "BrickletGPSV2Altitude"), "Altitude", "Number:Length").withConfigDescriptionURI(URI.create("channel-type:tinkerforge:BrickletGPSV2Altitude")).withDescription("The measured altitude")
.withStateDescription(StateDescriptionFragmentBuilder.create().withPattern("%.2f %unit%").withReadOnly(true).build().toStateDescription()).build();
            case "BrickletGPSV2GeoidalSeparation":
                return ChannelTypeBuilder.state(new ChannelTypeUID("tinkerforge", "BrickletGPSV2GeoidalSeparation"), "Geoidal Separation", "Number:Length").withConfigDescriptionURI(URI.create("channel-type:tinkerforge:BrickletGPSV2GeoidalSeparation")).withDescription("The geoidal separation corresponding to the current altitude")
.withStateDescription(StateDescriptionFragmentBuilder.create().withPattern("%.2f %unit%").withReadOnly(true).build().toStateDescription()).build();
            case "BrickletGPSV2Course":
                return ChannelTypeBuilder.state(new ChannelTypeUID("tinkerforge", "BrickletGPSV2Course"), "Course", "Number:Angle").withConfigDescriptionURI(URI.create("channel-type:tinkerforge:BrickletGPSV2Course")).withDescription("The current course. A course of 0° means the Bricklet is traveling north bound and 90° means it is traveling east bound. Please note that this only returns useful values if an actual movement is present.")
.withStateDescription(StateDescriptionFragmentBuilder.create().withMinimum(BigDecimal.valueOf(0)).withMaximum(BigDecimal.valueOf(360)).withStep(BigDecimal.valueOf(0.01)).withPattern("%.2f %unit%").withReadOnly(true).build().toStateDescription()).build();
            case "BrickletGPSV2Speed":
                return ChannelTypeBuilder.state(new ChannelTypeUID("tinkerforge", "BrickletGPSV2Speed"), "Speed", "Number:Speed").withConfigDescriptionURI(URI.create("channel-type:tinkerforge:BrickletGPSV2Speed")).withDescription("The current speed. Please note that this only returns useful values if an actual movement is present.")
.withStateDescription(StateDescriptionFragmentBuilder.create().withPattern("%.2f %unit%").withReadOnly(true).build().toStateDescription()).build();
            case "BrickletGPSV2DateTime":
                return ChannelTypeBuilder.state(new ChannelTypeUID("tinkerforge", "BrickletGPSV2DateTime"), "Date Time", "DateTime").withConfigDescriptionURI(URI.create("channel-type:tinkerforge:BrickletGPSV2DateTime")).withDescription("The current date and time.").build();
            case "BrickletGPSV2Restart":
                return ChannelTypeBuilder.state(new ChannelTypeUID("tinkerforge", "BrickletGPSV2Restart"), "Restart", "String").withConfigDescriptionURI(URI.create("channel-type:tinkerforge:BrickletGPSV2Restart")).withDescription("Restarts the GPS Bricklet, the following restart types are available:<ul><li>Hot start (use all available data in the NV store)</li><li>Warm start (don't use ephemeris at restart)</li><li>Cold start (don't use time, position, almanacs and ephemeris at restart)</li><li>Factory reset (clear all system/user configurations at restart)</li></ul>")
.withCommandDescription(CommandDescriptionBuilder.create().withCommandOption(new CommandOption("0", "Hot Start")).withCommandOption(new CommandOption("1", "Warm Start")).withCommandOption(new CommandOption("2", "Cold Start")).withCommandOption(new CommandOption("3", "Factory reset")).build()).build();
default:
                break;
        }

        return null;
    }

    public static ThingType getThingType(ThingTypeUID thingTypeUID) {
             Map<String, String> thingTypeProperties = ThingTypeBuilder.instance(thingTypeUID, "unused").build().getProperties();
             Map<String, String> props = new HashMap<String, String>(thingTypeProperties);
             props.putIfAbsent(TinkerforgeBindingConstants.PROPERTY_MINIMUM_FIRMWARE_VERSION, DEVICE_INFO.minimumFWVersion);
        return ThingTypeBuilder.instance(thingTypeUID, "Tinkerforge GPS Bricklet 2.0").isListed(false).withSupportedBridgeTypeUIDs(Arrays.asList(TinkerforgeBindingConstants.THING_TYPE_BRICK_DAEMON.toString())).withConfigDescriptionURI(URI.create("thing-type:tinkerforge:" + thingTypeUID.getId())).withDescription("Determine position, velocity and altitude using GPS").withChannelDefinitions(Arrays.asList(new ChannelDefinitionBuilder("BrickletGPSV2Location", new ChannelTypeUID("tinkerforge", "BrickletGPSV2Coordinates")).withLabel("Location").build(), new ChannelDefinitionBuilder("BrickletGPSV2Fix", new ChannelTypeUID("tinkerforge", "BrickletGPSV2Fix")).withLabel("Fix").build(), new ChannelDefinitionBuilder("BrickletGPSV2SatellitesInView", new ChannelTypeUID("tinkerforge", "BrickletGPSV2SatellitesInView")).withLabel("Satellites In View").build(), new ChannelDefinitionBuilder("BrickletGPSV2Altitude", new ChannelTypeUID("tinkerforge", "BrickletGPSV2Altitude")).withLabel("Altitude").build(), new ChannelDefinitionBuilder("BrickletGPSV2GeoidalSeparation", new ChannelTypeUID("tinkerforge", "BrickletGPSV2GeoidalSeparation")).withLabel("Geoidal Separation").build(), new ChannelDefinitionBuilder("BrickletGPSV2Course", new ChannelTypeUID("tinkerforge", "BrickletGPSV2Course")).withLabel("Course").build(), new ChannelDefinitionBuilder("BrickletGPSV2Speed", new ChannelTypeUID("tinkerforge", "BrickletGPSV2Speed")).withLabel("Speed").build(), new ChannelDefinitionBuilder("BrickletGPSV2DateTime", new ChannelTypeUID("tinkerforge", "BrickletGPSV2DateTime")).withLabel("Date Time").build(), new ChannelDefinitionBuilder("BrickletGPSV2PulsePerSecond", new ChannelTypeUID("system", "trigger")).withLabel("Pulse Per Second").withDescription("This channel is triggered precisely once per second, see PPS: https://en.wikipedia.org/wiki/Pulse-per-second_signal.<br/><br/>The precision of two subsequent pulses will be skewed because of the latency in the USB/RS485/Ethernet connection. But in the long run this will be very precise. For example a count of 3600 pulses will take exactly 1 hour.").build(), new ChannelDefinitionBuilder("BrickletGPSV2Restart", new ChannelTypeUID("tinkerforge", "BrickletGPSV2Restart")).withLabel("Restart").build())).withProperties(props).build();
    }

    public static @Nullable ConfigDescription getConfigDescription(URI uri) {
        switch(uri.toASCIIString()) {
            case "thing-type:tinkerforge:brickletgpsv2":
                return ConfigDescriptionBuilder.create(uri).withParameters(Arrays.asList(ConfigDescriptionParameterBuilder.create("fixLEDConfig", Type.INTEGER).withDefault("3").withDescription("The fix LED configuration. By default the LED shows if the Bricklet got a GPS fix yet. If a fix is established the LED turns on. If there is no fix then the LED is turned off.<br/><br/>You can also turn the LED permanently on/off, show a heartbeat or let it blink in sync with the PPS (pulse per second) output of the GPS module.<br/><br/>If the Bricklet is in bootloader mode, the LED is off.").withLabel("Fix LED").withAdvanced(true).withLimitToOptions(true).withOptions(Arrays.asList(new ParameterOption("0", "Off"), new ParameterOption("1", "On"), new ParameterOption("2", "Show Heartbeat"), new ParameterOption("3", "Show Fix"), new ParameterOption("4", "Show PPS"))).build(), ConfigDescriptionParameterBuilder.create("enableSBAS", Type.BOOLEAN).withDefault("true").withDescription("If SBAS is enabled, the position accuracy increases (if SBAS satellites are in view), but the update rate is limited to 5Hz. With SBAS disabled the update rate is increased to 10Hz.").withLabel("SBAS").withAdvanced(true).build(), ConfigDescriptionParameterBuilder.create("statusUpdateInterval", Type.INTEGER).withDefault("1000").withDescription("Specifies the update interval for the status in milliseconds. A value of 0 disables automatic updates.").withGroupName("update_intervals").withLabel("Status Update Interval").withUnit("ms").withMinimum(BigDecimal.valueOf(0)).withMaximum(BigDecimal.valueOf(4294967295L)).build(), ConfigDescriptionParameterBuilder.create("altitudeUpdateInterval", Type.INTEGER).withDefault("1000").withDescription("Specifies the update interval for the altitude and geodial separation in milliseconds. A value of 0 disables automatic updates.").withGroupName("update_intervals").withLabel("Altitude Update Interval").withUnit("ms").withMinimum(BigDecimal.valueOf(0)).withMaximum(BigDecimal.valueOf(4294967295L)).build(), ConfigDescriptionParameterBuilder.create("motionUpdateInterval", Type.INTEGER).withDefault("1000").withDescription("Specifies the update interval for the course and speed in milliseconds. A value of 0 disables automatic updates.").withGroupName("update_intervals").withLabel("Motion Update Interval").withUnit("ms").withMinimum(BigDecimal.valueOf(0)).withMaximum(BigDecimal.valueOf(4294967295L)).build(), ConfigDescriptionParameterBuilder.create("statusLEDConfig", Type.INTEGER).withDefault("3").withDescription("The status LED configuration. By default the LED shows communication traffic between Brick and Bricklet, it flickers once for every 10 received data packets.<br/><br/>You can also turn the LED permanently on/off or show a heartbeat.<br/><br/>If the Bricklet is in bootloader mode, the LED is will show heartbeat by default.").withLabel("Status LED Configuration").withAdvanced(true).withLimitToOptions(true).withOptions(Arrays.asList(new ParameterOption("0", "Off"), new ParameterOption("1", "On"), new ParameterOption("2", "Show Heartbeat"), new ParameterOption("3", "Show Status"))).build())).withParameterGroups(Arrays.asList(new ConfigDescriptionParameterGroup("update_intervals", "null", true, "Update Intervals", "Update Intervals"))).build();
            case "channel-type:tinkerforge:BrickletGPSV2Coordinates":
                return ConfigDescriptionBuilder.create(uri).withParameters(Arrays.asList(ConfigDescriptionParameterBuilder.create("updateInterval", Type.INTEGER).withDefault("1000").withDescription("Specifies the update interval in milliseconds. A value of 0 disables automatic updates.").withGroupName("update_intervals").withLabel("Update Interval").withUnit("ms").withMinimum(BigDecimal.valueOf(0)).withMaximum(BigDecimal.valueOf(4294967295L)).build())).withParameterGroups(Arrays.asList()).build();
            case "channel-type:tinkerforge:BrickletGPSV2Fix":
                return ConfigDescriptionBuilder.create(uri).withParameters(Arrays.asList()).withParameterGroups(Arrays.asList()).build();
            case "channel-type:tinkerforge:BrickletGPSV2SatellitesInView":
                return ConfigDescriptionBuilder.create(uri).withParameters(Arrays.asList()).withParameterGroups(Arrays.asList()).build();
            case "channel-type:tinkerforge:BrickletGPSV2Altitude":
                return ConfigDescriptionBuilder.create(uri).withParameters(Arrays.asList()).withParameterGroups(Arrays.asList()).build();
            case "channel-type:tinkerforge:BrickletGPSV2GeoidalSeparation":
                return ConfigDescriptionBuilder.create(uri).withParameters(Arrays.asList()).withParameterGroups(Arrays.asList()).build();
            case "channel-type:tinkerforge:BrickletGPSV2Course":
                return ConfigDescriptionBuilder.create(uri).withParameters(Arrays.asList()).withParameterGroups(Arrays.asList()).build();
            case "channel-type:tinkerforge:BrickletGPSV2Speed":
                return ConfigDescriptionBuilder.create(uri).withParameters(Arrays.asList()).withParameterGroups(Arrays.asList()).build();
            case "channel-type:tinkerforge:BrickletGPSV2DateTime":
                return ConfigDescriptionBuilder.create(uri).withParameters(Arrays.asList(ConfigDescriptionParameterBuilder.create("updateInterval", Type.INTEGER).withDefault("1000").withDescription("Specifies the update interval in milliseconds. A value of 0 disables automatic updates.").withGroupName("update_intervals").withLabel("Update Interval").withUnit("ms").withMinimum(BigDecimal.valueOf(0)).withMaximum(BigDecimal.valueOf(4294967295L)).build())).withParameterGroups(Arrays.asList()).build();
            case "channel-type:tinkerforge:BrickletGPSV2Restart":
                return ConfigDescriptionBuilder.create(uri).withParameters(Arrays.asList()).withParameterGroups(Arrays.asList()).build();
            default:
                break;
        }
        return null;
    }

        @Override
    public void refreshValue(String channel, org.eclipse.smarthome.config.core.Configuration config, org.eclipse.smarthome.config.core.Configuration channelConfig, BiConsumer<String, org.eclipse.smarthome.core.types.State> updateStateFn, BiConsumer<String, String> triggerChannelFn) throws TinkerforgeException {
        BrickletGPSV2Config cfg = (BrickletGPSV2Config) config.as(BrickletGPSV2Config.class);
switch(channel) {
            case "BrickletGPSV2Location":
               return;
            case "BrickletGPSV2Fix":
                   {
            BrickletGPSV2.Status value = this.getStatus();
            if(true)
                updateStateFn.accept(channel, transformBrickletGPSV2FixGetter0(value, cfg));
        }
                   return;
            case "BrickletGPSV2SatellitesInView":
                   {
            BrickletGPSV2.Status value = this.getStatus();
            if(true)
                updateStateFn.accept(channel, transformBrickletGPSV2SatellitesInViewGetter0(value, cfg));
        }
                   return;
            case "BrickletGPSV2Altitude":
                   {
            BrickletGPSV2.Altitude value = this.getAltitude();
            if(true)
                updateStateFn.accept(channel, transformBrickletGPSV2AltitudeGetter0(value, cfg));
        }
                   return;
            case "BrickletGPSV2GeoidalSeparation":
                   {
            BrickletGPSV2.Altitude value = this.getAltitude();
            if(true)
                updateStateFn.accept(channel, transformBrickletGPSV2GeoidalSeparationGetter0(value, cfg));
        }
                   return;
            case "BrickletGPSV2Course":
                   {
            BrickletGPSV2.Motion value = this.getMotion();
            if(true)
                updateStateFn.accept(channel, transformBrickletGPSV2CourseGetter0(value, cfg));
        }
                   return;
            case "BrickletGPSV2Speed":
                   {
            BrickletGPSV2.Motion value = this.getMotion();
            if(true)
                updateStateFn.accept(channel, transformBrickletGPSV2SpeedGetter0(value, cfg));
        }
                   return;
            case "BrickletGPSV2DateTime":
                   {
            BrickletGPSV2.DateTime value = this.getDateTime();
            if(true)
                updateStateFn.accept(channel, transformBrickletGPSV2DateTimeGetter0(value, cfg));
        }
                   return;
            case "BrickletGPSV2PulsePerSecond":
               return;
            case "BrickletGPSV2Restart":
               return;
default:
                logger.warn("Refresh for unknown channel {}", channel);
                break;
        }
    }
    

        @Override
    public List<SetterRefresh> handleCommand(org.eclipse.smarthome.config.core.Configuration config, org.eclipse.smarthome.config.core.Configuration channelConfig, String channel, Command command) throws TinkerforgeException {
        List<SetterRefresh> result = Collections.emptyList();
        
        switch(channel) {
            case "BrickletGPSV2Restart":
                if (command instanceof StringType) {
                    StringType cmd = (StringType) command;
this.restart(Integer.valueOf(cmd.toString()));
                }
        
                else {
                    logger.warn("Command type {} not supported for channel {}. Please use one of StringType.", command.getClass().getName(), channel);
                }
                
                break;
default:
                logger.warn("Command for unknown channel {}", channel);
        }
        return result;
    }

        private org.eclipse.smarthome.core.types.State transformBrickletGPSV2LocationCallback0(long latitude, char ns, long longitude, char ew, BrickletGPSV2Config cfg) {
        return new PointType(new DecimalType(latitude / 1000000.0 * (ns == 'N' ? 1 : -1)), new DecimalType(longitude / 1000000.0 * (ew == 'E' ? 1 : -1)));
    }
	    private org.eclipse.smarthome.core.types.State transformBrickletGPSV2FixCallback0(boolean hasFix, int satellitesView, BrickletGPSV2Config cfg) {
        return hasFix ? OpenClosedType.CLOSED : OpenClosedType.OPEN;
    }
	    private org.eclipse.smarthome.core.types.State transformBrickletGPSV2SatellitesInViewCallback0(boolean hasFix, int satellitesView, BrickletGPSV2Config cfg) {
        return new DecimalType(satellitesView);
    }
	    private org.eclipse.smarthome.core.types.State transformBrickletGPSV2AltitudeCallback0(int altitude, int geoidalSeparation, BrickletGPSV2Config cfg) {
        return new QuantityType<>(altitude / 100.0, SIUnits.METRE);
    }
	    private org.eclipse.smarthome.core.types.State transformBrickletGPSV2GeoidalSeparationCallback0(int altitude, int geoidalSeparation, BrickletGPSV2Config cfg) {
        return new QuantityType<>(geoidalSeparation / 100.0, SIUnits.METRE);
    }
	    private org.eclipse.smarthome.core.types.State transformBrickletGPSV2CourseCallback0(long course, long speed, BrickletGPSV2Config cfg) {
        return new QuantityType<>(course / 100.0, SmartHomeUnits.DEGREE_ANGLE);
    }
	    private org.eclipse.smarthome.core.types.State transformBrickletGPSV2SpeedCallback0(long course, long speed, BrickletGPSV2Config cfg) {
        return new QuantityType<>(speed / 100.0, SIUnits.KILOMETRE_PER_HOUR);
    }
	    private org.eclipse.smarthome.core.types.State transformBrickletGPSV2DateTimeCallback0(long date, long time, BrickletGPSV2Config cfg) {
        return new DateTimeType(Helper.parseGPSDateTime(date, time).withZoneSameInstant(ZoneId.systemDefault()));
    }
	    private String transformBrickletGPSV2PulsePerSecondCallback0(BrickletGPSV2Config cfg) {
        return "";
    }
	    private org.eclipse.smarthome.core.types.State transformBrickletGPSV2FixGetter0(BrickletGPSV2.Status value, BrickletGPSV2Config cfg) {
        return value.hasFix ? OpenClosedType.CLOSED : OpenClosedType.OPEN;
    }
	    private org.eclipse.smarthome.core.types.State transformBrickletGPSV2SatellitesInViewGetter0(BrickletGPSV2.Status value, BrickletGPSV2Config cfg) {
        return new DecimalType(value.satellitesView);
    }
	    private org.eclipse.smarthome.core.types.State transformBrickletGPSV2AltitudeGetter0(BrickletGPSV2.Altitude value, BrickletGPSV2Config cfg) {
        return new QuantityType<>(value.altitude / 100.0, SIUnits.METRE);
    }
	    private org.eclipse.smarthome.core.types.State transformBrickletGPSV2GeoidalSeparationGetter0(BrickletGPSV2.Altitude value, BrickletGPSV2Config cfg) {
        return new QuantityType<>(value.geoidalSeparation / 100.0, SIUnits.METRE);
    }
	    private org.eclipse.smarthome.core.types.State transformBrickletGPSV2CourseGetter0(BrickletGPSV2.Motion value, BrickletGPSV2Config cfg) {
        return new QuantityType<>(value.course / 100.0, SmartHomeUnits.DEGREE_ANGLE);
    }
	    private org.eclipse.smarthome.core.types.State transformBrickletGPSV2SpeedGetter0(BrickletGPSV2.Motion value, BrickletGPSV2Config cfg) {
        return new QuantityType<>(value.speed / 100.0, SIUnits.KILOMETRE_PER_HOUR);
    }
	    private org.eclipse.smarthome.core.types.State transformBrickletGPSV2DateTimeGetter0(BrickletGPSV2.DateTime value, BrickletGPSV2Config cfg) {
        return new DateTimeType(Helper.parseGPSDateTime(value.date, value.time).withZoneSameInstant(ZoneId.systemDefault()));
    }

}