Skip to content

Plugin file

Plugin configuration file
{
    "name": "pepperl-fuchs-wilsen-sonic-level",
    "version": "1.0.0",
    "description": "Wireless ultrasonic sensor with LoRaWAN interface",
    "author": "Thinger.io",
    "license": "MIT",
    "repository": {
        "type": "git",
        "url": "https://github.com/thinger-io/plugins.git",
        "directory": "pepperl-fuchs-wilsen-sonic-level"
    },
    "metadata": {
        "name": "Pepperl-Fuchs WILSEN-SONIC-LEVEL",
        "description": "Wireless ultrasonic sensor with LoRaWAN interface",
        "image": "assets/wilsen-sonic-level.png",
        "category": "devices",
        "vendor": "pepperl-fuchs"
    },
    "resources": {
        "products": [
            {
                "description": "Wireless ultrasonic sensor with LoRaWAN interface",
                "enabled": true,
                "name": "Pepperl-Fuchs WILSEN-SONIC-LEVEL",
                "product": "pepperl_fuchs_wilsen_sonic_level",
                "profile": {
                    "api": {
                        "downlink": {
                            "enabled": true,
                            "handle_connectivity": false,
                            "request": {
                                "data": {
                                    "path": "/downlink",
                                    "payload": "{\n    \"data\"    : \"{{payload.data=\"\"}}\",\n    \"port\"    :  {{payload.port=85}},\n    \"priority\":  {{payload.priority=3}},\n    \"confirmed\" :  {{payload.confirmed=false}},\n    \"uplink\"  :  {{property.uplink}} \n}",
                                    "payload_function": "",
                                    "payload_type": "",
                                    "plugin": "{{property.uplink.source}}",
                                    "target": "plugin_endpoint"
                                }
                            }
                        },
                        "uplink": {
                            "device_id_resolver": "getId",
                            "enabled": true,
                            "handle_connectivity": true,
                            "request": {
                                "data": {
                                    "payload": "{{payload}}",
                                    "payload_function": "",
                                    "payload_type": "source_payload",
                                    "resource_stream": "uplink",
                                    "target": "resource_stream"
                                }
                            }
                        }
                    },
                    "autoprovisions": {
                        "device_autoprovisioning": {
                            "config": {
                                "mode": "pattern",
                                "pattern": "wilsen-sonic-.*"
                            },
                            "enabled": true
                        }
                    },
                    "buckets": {
                        "pepperl_fuchs_wilsen_sonic_level_data": {
                            "backend": "mongodb",
                            "data": {
                                "payload": "{{payload}}",
                                "payload_function": "",
                                "payload_type": "source_payload",
                                "resource_stream": "uplink_decoded",
                                "source": "resource_stream"
                            },
                            "enabled": true,
                            "retention": {
                                "period": 3,
                                "unit": "months"
                            },
                            "tags": []
                        }
                    },
                    "code": {
                        "code": "function getAmplitude(payload) {\r\n    return payload.amplitude;\r\n}\r\n\r\nfunction getBattery(payload) {\r\n    return payload.battery_vol;\r\n}\r\n\r\nfunction getFillingLevel(payload) {\r\n    return payload.fillinglvl;\r\n}\r\n\r\nfunction getLatitude(payload) {\r\n    return payload.latitude;\r\n}\r\n\r\nfunction getLongitude(payload) {\r\n    return payload.longitude;\r\n}\r\n\r\nfunction getProximity(payload) {\r\n    return payload.proxx;\r\n}\r\n\r\nfunction getSerialNumber(payload) {\r\n    return payload.serial_nr;\r\n}\r\n\r\nfunction getTemperature(payload) {\r\n    return payload.temp;\r\n}\r\n\r\nfunction getWaterBodyLevel(payload) {\r\n    return payload.water_body_level_mm;\r\n}\r\n\r\n\r\n\r\n\r\nfunction decodeThingerUplink(thingerData) {\r\n    // 0. If data has already been decoded, we will return it\r\n    if (thingerData.decodedPayload) return thingerData.decodedPayload;\r\n    \r\n    // 1. Extract and Validate Input\r\n    // We need 'payload' (hex string) and 'fPort' (integer)\r\n    const hexPayload = thingerData.payload || \"\";\r\n    const port = thingerData.fPort || 1;\r\n\r\n    // 2. Convert Hex String to Byte Array\r\n    const bytes = [];\r\n    for (let i = 0; i < hexPayload.length; i += 2) {\r\n        bytes.push(parseInt(hexPayload.substr(i, 2), 16));\r\n    }\r\n\r\n    // 3. Dynamic Function Detection and Execution\r\n    \r\n    // CASE A: (The Things Stack v3)\r\n    if (typeof decodeUplink === 'function') {\r\n        try {\r\n            const input = {\r\n                bytes: bytes,\r\n                fPort: port\r\n            };\r\n            var result = decodeUplink(input);\r\n            \r\n            if (result.data) return result.data;\r\n\r\n            return result; \r\n        } catch (e) {\r\n            console.error(\"Error inside decodeUplink:\", e);\r\n            throw e;\r\n        }\r\n    }\r\n\r\n    // CASE B: Legacy TTN (v2)\r\n    else if (typeof Decoder === 'function') {\r\n        try {\r\n            return Decoder(bytes, port);\r\n        } catch (e) {\r\n            console.error(\"Error inside Decoder:\", e);\r\n            throw e;\r\n        }\r\n    }\r\n\r\n    // CASE C: No decoder found\r\n    else {\r\n        throw new Error(\"No compatible TTN decoder function (decodeUplink or Decoder) found in scope.\");\r\n    }\r\n}\r\n\r\n\r\n// TTN decoder\r\n'use strict';\r\n\r\nfunction decodeUplink(input) {\r\n    var hexStr = byte2HexString(input.bytes);\r\n    var obj = payloadParser(hexStr);\r\n\r\n    return {\r\n        data: obj,\r\n        warnings: [],\r\n        errors: []\r\n    };\r\n}\r\n\r\n/**\r\n * This is the function to create a payload object by decoding hex string\r\n * @param {String} hexStr\r\n * @return {Object}\r\n */\r\nfunction payloadParser(hexStr) {\r\n    const LoRaMessgeType = {\r\n        0: 'Unconfirmed',\r\n        1: 'Confirmed'\r\n    };\r\n    const SonicBeamWidth = {\r\n        254: 'Small',\r\n        253: 'Medium',\r\n        252: 'Wide',\r\n        55: 'User-defined',\r\n    };\r\n    const SonicBurstLength = {\r\n        5: 'Normal',\r\n        3: 'Short',\r\n        16: 'Very short',\r\n    };\r\n    const SonicTransmittingPower = {\r\n        63: 'High',\r\n        40: 'Medium',\r\n        12: 'Low'\r\n    };\r\n    const SonicSensitivity = {\r\n        63: 'Maximum',\r\n        51: 'Very high',\r\n        48: 'High',\r\n        38: 'Medium',\r\n        27: 'Low',\r\n        15: 'Minimum',\r\n    };\r\n    const SonicEvaluationMethod = {\r\n        1: 'Average value'\r\n    };\r\n    const SonicApplicationFilter = {\r\n        1: 'Container filling'\r\n    };\r\n    const ValveStatus = {\r\n        0: 'Closed',\r\n        1: 'Open',\r\n        2: 'Undefined',\r\n        3: 'Not connected',\r\n        7: 'Not inquired'\r\n    }\r\n    const SensorDetails = {\r\n        0: 'Low',\r\n        1: 'High',\r\n        7: 'Not inquired',\r\n        8: 'Short circuit',\r\n        9: 'Not connected',\r\n        10: 'Invalid current level',\r\n    }\r\n    const ValveOpenSignal = {\r\n        1: 'Sensor 1',\r\n        2: 'Sensor 2'\r\n    };\r\n    const ValveTriggerEventType = {\r\n        1: 'State change',\r\n        2: 'Valve open',\r\n        3: 'Valve closed',\r\n    };\r\n    const NodeOutputLogic = {\r\n        1: 'Normally open',\r\n        2: 'Normally closed'\r\n    };\r\n    const SensorStatus = {\r\n        0: 'No target detected',\r\n        1: 'Target detected',\r\n        7: 'Not inquired',\r\n        8: 'Short circuit',\r\n        9: 'Not connected',\r\n        10: 'Invalid current level',\r\n    }\r\n    const NodeTriggerEventType = {\r\n        1: 'State change',\r\n        2: 'Target detected',\r\n        3: 'No target detected',\r\n    };\r\n    const GPSAccuracyMode = {\r\n        1: 'Eco mode',\r\n        2: 'Precision mode',\r\n    };\r\n    var len;\r\n    var sID;\r\n    var obj = {};\r\n\r\n    obj.payload = hexStr;\r\n    for (var i = 0; i < hexStr.length; i = i + 2) {\r\n        len = parseInt(hexStr.substr(i, 2), 16);\r\n        sID = hexStr.substr(i + 2, 4);\r\n\r\n        if (sID == '0201') { // 'Temperature'\r\n            obj.temp = parseFloat(hex2float(hexStr.substr(i + 6, 8)).toFixed(1)); // float\r\n        }\r\n        else if (sID == '0B01') { // 'Proximity'\r\n            obj.proxx = parseInt(hexStr.substr(i + 6, 4), 16); // uint16\r\n        }\r\n        else if (sID == '0B02') { // 'Proximity in mm'\r\n            obj.proxx_mm = parseInt(hexStr.substr(i + 6, 4), 16); // uint16\r\n        }\r\n        else if (sID == '0B06') { // 'Fillinglevel'\r\n            obj.fillinglvl = parseInt(hexStr.substr(i + 6, 2), 16); // uint8\r\n        }\r\n        else if (sID == '0B07') { // 'Amplitude'\r\n            obj.amplitude = parseInt(hexStr.substr(i + 6, 2), 16); // uint8\r\n        }\r\n        else if (sID == '0B08') { // 'Water Body Level'\r\n            obj.water_body_level_mm = parseInt(hexStr.substr(i + 6, 4), 16); // uint16\r\n        }\r\n        else if (sID == '0C01') { // 'Valve'\r\n            obj.valve = parseInt(hexStr.substr(i + 6, 2), 16); // uint8\r\n            obj.valveChecksum = parseInt(hexStr.substr(i + 8, 2), 16); // uint8\r\n        }\r\n        else if (sID == '0C02') { // 'Valve Status'\r\n            obj.valve_status = parseInt(hexStr.substr(i + 6, 2), 16); // uint8\r\n            const valve1Status = obj.valve_status & 0x0F;\r\n            const valve2Status = (obj.valve_status >> 4) & 0x0F;\r\n            obj.valve_1_status = (ValveStatus[valve1Status] ? ValveStatus[valve1Status] : 'Invalid');\r\n            obj.valve_2_status = (ValveStatus[valve2Status] ? ValveStatus[valve2Status] : 'Invalid');\r\n        }\r\n        else if (sID == '0C03') { // 'Sensor Details'\r\n            obj.sensor_details = parseInt(hexStr.substr(i + 6, 4), 16); // uint16\r\n            const sensor1details = obj.sensor_details & 0x000F;\r\n            const sensor2details = (obj.sensor_details >> 4) & 0x000F;\r\n            const sensor3details = (obj.sensor_details >> 8) & 0x000F;\r\n            const sensor4details = (obj.sensor_details >> 12) & 0x000F;\r\n            obj.sensor_1_details = (SensorDetails[sensor1details] ? SensorDetails[sensor1details] : 'Invalid');\r\n            obj.sensor_2_details = (SensorDetails[sensor2details] ? SensorDetails[sensor2details] : 'Invalid');\r\n            obj.sensor_3_details = (SensorDetails[sensor3details] ? SensorDetails[sensor3details] : 'Invalid');\r\n            obj.sensor_4_details = (SensorDetails[sensor4details] ? SensorDetails[sensor4details] : 'Invalid');\r\n        }\r\n        else if (sID == '0C04') { // 'Sensor Status'\r\n            obj.sensor_status = parseInt(hexStr.substr(i + 6, 2), 16); // uint8\r\n            const sensor1Status = obj.sensor_status & 0x0F;\r\n            const sensor2Status = (obj.sensor_status >> 4) & 0x0F;\r\n            obj.sensor_1_status = (SensorStatus[sensor1Status] ? SensorStatus[sensor1Status] : 'Invalid');\r\n            obj.sensor_2_status = (SensorStatus[sensor2Status] ? SensorStatus[sensor2Status] : 'Invalid');\r\n        }\r\n        else if (sID == '2A25') { // 'Serial Number'\r\n            obj.serial_nr = hex2string(hexStr.substr(i + 6, 28));\r\n        }\r\n        else if (sID == '2A26') { // 'Serial Number - 6 bytes uint'\r\n            obj.serial_nr_uint = parseInt(hexStr.substr(i + 6, 12), 16); // uint24\r\n        }\r\n        else if (sID == '3101') { // 'LoRa Transmission Counter'\r\n            obj.lora_count = parseInt(hexStr.substr(i + 6, 4), 16); // uint16\r\n        }\r\n        else if (sID == '3102') { // 'GPS Acquisition Counter'\r\n            obj.gps_count = parseInt(hexStr.substr(i + 6, 4), 16); // uint16\r\n        }\r\n        else if (sID == '3103') { // 'US Measurement Counter'\r\n            obj.us_sensor_count = parseInt(hexStr.substr(i + 6, 8), 16); // uint32\r\n        }\r\n        else if (sID == '3104') { // 'Sensor Measurement Counter'\r\n            obj.sensing_count = parseInt(hexStr.substr(i + 6, 8), 16); // uint32\r\n        }\r\n        else if (sID == '5001') { // 'GPS Latitude'\r\n            obj.latitude = parseFloat((number2Int32(parseInt(hexStr.substr(i + 6, 8), 16)) / 1000000).toFixed(6));\r\n        }\r\n        else if (sID == '5002') { // 'GPS Longitude'\r\n            obj.longitude = parseFloat((number2Int32(parseInt(hexStr.substr(i + 6, 8), 16)) / 1000000).toFixed(6));\r\n        }\r\n        else if (sID == '5101') { // 'Battery'\r\n            if (parseInt(hexStr.substr(i + 4, 2), 16) == 1) {\r\n                obj.battery_vol = parseInt(hexStr.substr(i + 6, 2), 16) / 10; // uint8\r\n            }\r\n        }\r\n\r\n        // Downlink ACK: Device Config\r\n        else if (sID == 'F101') {\r\n            obj.ble_enable = (parseInt(hexStr.substr(i + 6, 2), 16) > 0);\r\n        }\r\n        else if (sID == 'F102') {\r\n            obj.device_name = hex2string(hexStr.substr(i + 6, 32));\r\n        }\r\n        else if (sID == 'F103') {\r\n            obj.reset_counter = 'done';\r\n        }\r\n        else if (sID == 'F104') {\r\n            obj.factory_reset = 'done';\r\n        }\r\n        else if (sID == 'F105') {\r\n            obj.change_password = 'done';\r\n        }\r\n        else if (sID == 'F108') {\r\n            obj.device_name_1 = hex2string(hexStr.substr(i + 6, 16));\r\n        }\r\n        else if (sID == 'F109') {\r\n            obj.device_name_2 = hex2string(hexStr.substr(i + 6, 16));\r\n        }     \r\n \r\n        // Downlink ACK: GPS Config\r\n        else if (sID == 'F201') {\r\n            obj.gps_acquisition_active = (parseInt(hexStr.substr(i + 6, 2), 16) > 0);\r\n        }\r\n        else if (sID == 'F202') {\r\n            obj.gps_acquisition_interval = parseInt(hexStr.substr(i + 6, 8), 16);\r\n        }\r\n        else if (sID == 'F203') {\r\n            obj.gps_next_acquisition = parseInt(hexStr.substr(i + 6, 8), 16);\r\n        }\r\n        else if (sID == 'F204') {\r\n            const gpsAccuracyModeIndex = parseInt(hexStr.substr(i + 6, 2), 16);\r\n            obj.gps_accuracy_mode = (GPSAccuracyMode[gpsAccuracyModeIndex] ? GPSAccuracyMode[gpsAccuracyModeIndex] : 'Invalid');\r\n        }\r\n        else if (sID == 'F205') {\r\n            const messageTypeIndex = parseInt(hexStr.substr(i + 6, 2), 16);\r\n            obj.gps_message_type = (LoRaMessgeType[messageTypeIndex] ? LoRaMessgeType[messageTypeIndex] : 'Invalid');\r\n        }\r\n        else if (sID == 'F206') {\r\n            obj.gps_number_of_transmission = parseInt(hexStr.substr(i + 6, 2), 16);\r\n        }\r\n        else if (sID == 'F207') {\r\n            obj.gps_localization = 'triggered';\r\n        }\r\n\r\n        // Downlink ACK: LoRa Config\r\n        else if (sID == 'F301') {\r\n            const messageTypeIndex = parseInt(hexStr.substr(i + 6, 2), 16);\r\n            obj.lora_message_type = (LoRaMessgeType[messageTypeIndex] ? LoRaMessgeType[messageTypeIndex] : 'Invalid');\r\n        }\r\n        else if (sID == 'F302') {\r\n            obj.lora_number_of_transmission = parseInt(hexStr.substr(i + 6, 2), 16);\r\n        }\r\n        else if (sID == 'F303') {\r\n            const spreadingFactor = parseInt(hexStr.substr(i + 6, 2), 16);\r\n            obj.lora_spreading_factor = (spreadingFactor == 255 ? 'ADR' : spreadingFactor);\r\n        }\r\n        else if (sID == 'F304') {\r\n            obj.lora_data_transmission_active = (parseInt(hexStr.substr(i + 6, 2), 16) > 0);\r\n        }\r\n        else if (sID == 'F305') {\r\n            obj.lora_transmission_interval = parseInt(hexStr.substr(i + 6, 8), 16);\r\n        }\r\n        else if (sID == 'F306') {\r\n            obj.lora_next_transmission = parseInt(hexStr.substr(i + 6, 8), 16);\r\n        }\r\n        else if (sID == 'F307') {\r\n            obj.lora_downlink_config = (parseInt(hexStr.substr(i + 6, 2), 16) > 0);\r\n        }\r\n        else if (sID == 'F308') {\r\n            obj.lora_downlink_config_ack = (parseInt(hexStr.substr(i + 6, 2), 16) > 0);\r\n        }\r\n        else if (sID == 'F309') {\r\n            obj.lora_sub_band = parseInt(hexStr.substr(i + 6, 2), 16);\r\n        }\r\n\r\n        // Downlink ACK: UltraSonic Config\r\n        else if (sID == 'F401') {\r\n            const SonicBeamWidthVal = parseInt(hexStr.substr(i + 6, 2), 16);\r\n            obj.us_beam_width = (SonicBeamWidth[SonicBeamWidthVal] ? SonicBeamWidth[SonicBeamWidthVal] : 'Invalid');\r\n        }\r\n        else if (sID == 'F402') {\r\n            const SonicBurstLengthVal = parseInt(hexStr.substr(i + 6, 2), 16);\r\n            obj.us_user_defined_burst_length = (SonicBurstLength[SonicBurstLengthVal] ? SonicBurstLength[SonicBurstLengthVal] : SonicBurstLengthVal);\r\n        }\r\n        else if (sID == 'F403') {\r\n            const SonicTransmittingPowerVal = parseInt(hexStr.substr(i + 6, 2), 16);\r\n            obj.us_user_defined_transmitting_power = (SonicTransmittingPower[SonicTransmittingPowerVal] ? SonicTransmittingPower[SonicTransmittingPowerVal] : SonicTransmittingPowerVal);\r\n        }\r\n        else if (sID == 'F404') {\r\n            const SonicSensitivityVal = parseInt(hexStr.substr(i + 6, 2), 16);\r\n            obj.us_user_defined_sensitivity = (SonicSensitivity[SonicSensitivityVal] ? SonicSensitivity[SonicSensitivityVal] : SonicSensitivityVal);\r\n        }\r\n        else if (sID == 'F405') {\r\n            obj.us_full_distance = parseInt(hexStr.substr(i + 6, 4), 16);\r\n        }\r\n        else if (sID == 'F406') {\r\n            obj.us_empty_distance = parseInt(hexStr.substr(i + 6, 4), 16);\r\n        }\r\n        else if (sID == 'F407') {\r\n            obj.us_measurement_sequence_active = (parseInt(hexStr.substr(i + 6, 2), 16) > 0);\r\n        }\r\n        else if (sID == 'F408') {\r\n            const evaluationMethodVal = parseInt(hexStr.substr(i + 6, 2), 16);\r\n            obj.us_evaluation_method = (SonicEvaluationMethod[evaluationMethodVal] ? SonicEvaluationMethod[evaluationMethodVal] : 'Invalid');\r\n        }\r\n        else if (sID == 'F409') {\r\n            obj.us_measurements_per_sequence = parseInt(hexStr.substr(i + 6, 2), 16);\r\n        }\r\n        else if (sID == 'F40A') {\r\n            obj.us_at_intervals_of = parseInt(hexStr.substr(i + 6, 4), 16);\r\n        }\r\n        else if (sID == 'F40B') {\r\n            obj.us_application_filter_active = (parseInt(hexStr.substr(i + 6, 2), 16) > 0);\r\n        }\r\n        else if (sID == 'F40C') {\r\n            const filterVal = parseInt(hexStr.substr(i + 6, 2), 16);\r\n            obj.us_post_processing_filter = (SonicApplicationFilter[filterVal] ? SonicApplicationFilter[filterVal] : 'Invalid');\r\n        }\r\n        else if (sID == 'F40D') {\r\n            obj.us_additional_measurement = parseInt(hexStr.substr(i + 6, 2), 16);\r\n        }\r\n        else if (sID == 'F40E') {\r\n            obj.water_body_level_active = parseInt(hexStr.substr(i + 6, 2), 16);\r\n        }\r\n        else if (sID == 'F40F') {\r\n            obj.distance_to_water_body_ground = parseInt(hexStr.substr(i + 6, 4), 16);\r\n        }\r\n\r\n        // Downlink ACK: Device Information\r\n        else if (sID == 'F501') {\r\n            obj.part_number = parseInt(hexStr.substr(i + 6, 8), 16);\r\n        }\r\n        else if (sID == 'F502') {\r\n            const major = parseInt(hexStr.substr(i + 6, 4), 16);\r\n            const minor = parseInt(hexStr.substr(i + 10, 4), 16);\r\n            const patch = parseInt(hexStr.substr(i + 14, 4), 16);\r\n            obj.hardware_revision = major + '.' + minor + '.' + patch;\r\n        }\r\n        else if (sID == 'F503') {\r\n            const major = parseInt(hexStr.substr(i + 6, 4), 16);\r\n            const minor = parseInt(hexStr.substr(i + 10, 4), 16);\r\n            const patch = parseInt(hexStr.substr(i + 14, 4), 16);\r\n            obj.firmware_revision = major + '.' + minor + '.' + patch;\r\n        }\r\n      \r\n        // Downlink ACK: Valve(UCC) Config\r\n      \telse if (sID == 'F601') {\r\n            const messageTypeIndex = parseInt(hexStr.substr(i + 6, 2), 16);\r\n            obj.valve_monitoring_message_type = (LoRaMessgeType[messageTypeIndex] ? LoRaMessgeType[messageTypeIndex] : 'Invalid');\r\n        }\r\n        else if (sID == 'F602') {\r\n            obj.valve_monitoring_interval = parseInt(hexStr.substr(i + 6, 8), 16);\r\n        }\r\n\r\n        // Downlink ACK: Valve Config\r\n      \telse if (sID == 'F701') {\r\n            const openSignalIndex = parseInt(hexStr.substr(i + 6, 2), 16);\r\n            obj.valve_1_open_signal = (ValveOpenSignal[openSignalIndex] ? ValveOpenSignal[openSignalIndex] : 'Invalid');\r\n        }\r\n        else if (sID == 'F702') {\r\n            obj.valve_1_event_driven_transmission = (parseInt(hexStr.substr(i + 6, 2), 16) > 0);\r\n        }\r\n        else if (sID == 'F703') {\r\n            const triggerEventIndex = parseInt(hexStr.substr(i + 6, 2), 16);\r\n            obj.valve_1_trigger_event = (ValveTriggerEventType[triggerEventIndex] ? ValveTriggerEventType[triggerEventIndex] : 'Invalid');\r\n        }\r\n        else if (sID == 'F704') {\r\n            const messageTypeIndex = parseInt(hexStr.substr(i + 6, 2), 16);\r\n            obj.valve_1_message_type = (LoRaMessgeType[messageTypeIndex] ? LoRaMessgeType[messageTypeIndex] : 'Invalid');\r\n        }\r\n        else if (sID == 'F705') {\r\n            obj.valve_1_num_of_transmission = parseInt(hexStr.substr(i + 6, 2), 16);\r\n        }\r\n        else if (sID == 'F706') {\r\n            obj.valve_1_monitoring_interval = parseInt(hexStr.substr(i + 6, 8), 16);\r\n        }\r\n        else if (sID == 'F707') {\r\n            const openSignalIndex = parseInt(hexStr.substr(i + 6, 2), 16);\r\n            obj.valve_2_open_signal = (ValveOpenSignal[openSignalIndex] ? ValveOpenSignal[openSignalIndex] : 'Invalid');\r\n        }\r\n        else if (sID == 'F708') {\r\n            obj.valve_2_event_driven_transmission = (parseInt(hexStr.substr(i + 6, 2), 16) > 0);\r\n        }\r\n        else if (sID == 'F709') {\r\n            const triggerEventIndex = parseInt(hexStr.substr(i + 6, 2), 16);\r\n            obj.valve_2_trigger_event = (ValveTriggerEventType[triggerEventIndex] ? ValveTriggerEventType[triggerEventIndex] : 'Invalid');\r\n        }\r\n        else if (sID == 'F70A') {\r\n            const messageTypeIndex = parseInt(hexStr.substr(i + 6, 2), 16);\r\n            obj.valve_2_message_type = (LoRaMessgeType[messageTypeIndex] ? LoRaMessgeType[messageTypeIndex] : 'Invalid');\r\n        }\r\n        else if (sID == 'F70B') {\r\n            obj.valve_2_num_of_transmission = parseInt(hexStr.substr(i + 6, 2), 16);\r\n        }\r\n        else if (sID == 'F70C') {\r\n            obj.valve_2_monitoring_interval = parseInt(hexStr.substr(i + 6, 8), 16);\r\n        }\r\n\r\n        // Downlink ACK: Node Config\r\n      \telse if (sID == 'F801') {\r\n            const outputLogicIndex = parseInt(hexStr.substr(i + 6, 2), 16);\r\n            obj.sensor_1_output_logic = (NodeOutputLogic[outputLogicIndex] ? NodeOutputLogic[outputLogicIndex] : 'Invalid');\r\n        }\r\n        else if (sID == 'F802') {\r\n            obj.sensor_1_event_driven_transmission = (parseInt(hexStr.substr(i + 6, 2), 16) > 0);\r\n        }\r\n        else if (sID == 'F803') {\r\n            const triggerEventIndex = parseInt(hexStr.substr(i + 6, 2), 16);\r\n            obj.sensor_1_trigger_event = (NodeTriggerEventType[triggerEventIndex] ? NodeTriggerEventType[triggerEventIndex] : 'Invalid');\r\n        }\r\n        else if (sID == 'F804') {\r\n            const messageTypeIndex = parseInt(hexStr.substr(i + 6, 2), 16);\r\n            obj.sensor_1_message_type = (LoRaMessgeType[messageTypeIndex] ? LoRaMessgeType[messageTypeIndex] : 'Invalid');\r\n        }\r\n        else if (sID == 'F805') {\r\n            obj.sensor_1_num_of_transmission = parseInt(hexStr.substr(i + 6, 2), 16);\r\n        }\r\n        else if (sID == 'F806') {\r\n            obj.sensor_1_monitoring_interval = parseInt(hexStr.substr(i + 6, 8), 16);\r\n        }\r\n        else if (sID == 'F807') {\r\n            const outputLogicIndex = parseInt(hexStr.substr(i + 6, 2), 16);\r\n            obj.sensor_2_output_logic = (NodeOutputLogic[outputLogicIndex] ? NodeOutputLogic[outputLogicIndex] : 'Invalid');\r\n        }\r\n        else if (sID == 'F808') {\r\n            obj.sensor_2_event_driven_transmission = (parseInt(hexStr.substr(i + 6, 2), 16) > 0);\r\n        }\r\n        else if (sID == 'F809') {\r\n            const triggerEventIndex = parseInt(hexStr.substr(i + 6, 2), 16);\r\n            obj.sensor_2_trigger_event = (NodeTriggerEventType[triggerEventIndex] ? NodeTriggerEventType[triggerEventIndex] : 'Invalid');\r\n        }\r\n        else if (sID == 'F80A') {\r\n            const messageTypeIndex = parseInt(hexStr.substr(i + 6, 2), 16);\r\n            obj.sensor_2_message_type = (LoRaMessgeType[messageTypeIndex] ? LoRaMessgeType[messageTypeIndex] : 'Invalid');\r\n        }\r\n        else if (sID == 'F80B') {\r\n            obj.sensor_2_num_of_transmission = parseInt(hexStr.substr(i + 6, 2), 16);\r\n        }\r\n        else if (sID == 'F80C') {\r\n            obj.sensor_2_monitoring_interval = parseInt(hexStr.substr(i + 6, 8), 16);\r\n        }\r\n\r\n        i = i + (len * 2);\r\n    }\r\n    return obj;\r\n}\r\n\r\nfunction byte2HexString(bytes) {\r\n    var retHexString = '';\r\n    for (var i_b = 0; i_b < bytes.length; i_b++) {\r\n        retHexString = retHexString.concat(('0' + (Number(bytes[i_b]).toString(16))).slice(-2).toUpperCase());\r\n    }\r\n    return retHexString;\r\n}\r\n\r\nfunction number2Int32(value) {\r\n    if (value > 0x7FFFFFFF) {\r\n        return (value - 0x100000000);\r\n    }\r\n    return value;\r\n}\r\n\r\nfunction hex2string(hexx) {\r\n    var hex = hexx.toString();\r\n    var str = '';\r\n    for (var j = 0;\r\n        (j < hex.length && hex.substr(j, 2) !== '00'); j += 2)\r\n        str += String.fromCharCode(parseInt(hex.substr(j, 2), 16));\r\n    return str;\r\n}\r\n\r\nfunction hex2float(hexstring) {\r\n    var bytes = [];\r\n    bytes[0] = parseInt(hexstring.substr(0, 2), 16);\r\n    bytes[1] = parseInt(hexstring.substr(2, 2), 16);\r\n    bytes[2] = parseInt(hexstring.substr(4, 2), 16);\r\n    bytes[3] = parseInt(hexstring.substr(6, 2), 16);\r\n    return decodeFloat(bytes, 1, 8, 23, -126, 127, false);\r\n}\r\n\r\nfunction decodeFloat(bytes, signBits, exponentBits, fractionBits, eMin, eMax, littleEndian) {\r\n    var binary = '';\r\n    for (var z = 0, l = bytes.length; z < l; z += 1) {\r\n        var bits = bytes[z].toString(2);\r\n        while (bits.length < 8) {\r\n            bits = '0' + bits;\r\n        }\r\n        if (littleEndian) {\r\n            binary = bits + binary;\r\n        } else {\r\n            binary += bits;\r\n        }\r\n    }\r\n    var sign = (binary.charAt(0) === '1') ? -1 : 1;\r\n    var exponent = parseInt(binary.substr(signBits, exponentBits), 2) - eMax;\r\n    var significandBase = binary.substr(signBits + exponentBits, fractionBits);\r\n    var significandBin = '1' + significandBase;\r\n    var cnt = 0;\r\n    var val = 1;\r\n    var significand = 0;\r\n    if (exponent == -eMax) {\r\n        if (significandBase.indexOf('1') === -1)\r\n            return 0;\r\n        else {\r\n            exponent = eMin;\r\n            significandBin = '0' + significandBase;\r\n        }\r\n    }\r\n    while (cnt < significandBin.length) {\r\n        significand += val * parseInt(significandBin.charAt(cnt));\r\n        val = val / 2;\r\n        cnt += 1;\r\n    }\r\n    return sign * significand * Math.pow(2, exponent);\r\n}\r\n",
                        "environment": "javascript",
                        "storage": "",
                        "version": "1.0"
                    },
                    "flows": {
                        "pepperl_fuchs_wilsen_sonic_level": {
                            "data": {
                                "payload": "{{payload}}",
                                "payload_function": "decodeThingerUplink",
                                "payload_type": "source_payload",
                                "resource": "uplink",
                                "source": "resource",
                                "update": "events"
                            },
                            "enabled": true,
                            "handle_connectivity": false,
                            "sink": {
                                "payload": "{{payload}}",
                                "payload_function": "",
                                "payload_type": "source_payload",
                                "resource_stream": "uplink_decoded",
                                "target": "resource_stream"
                            },
                            "split_data": false
                        }
                    },
                    "properties": {
                        "amplitude": {
                            "data": {
                                "payload": "{{payload}}",
                                "payload_function": "getAmplitude",
                                "payload_type": "source_payload",
                                "resource_stream": "uplink_decoded",
                                "source": "resource_stream"
                            },
                            "default": {
                                "source": "value"
                            },
                            "enabled": true
                        },
                        "battery": {
                            "data": {
                                "payload": "{{payload}}",
                                "payload_function": "getBattery",
                                "payload_type": "source_payload",
                                "resource_stream": "uplink_decoded",
                                "source": "resource_stream"
                            },
                            "default": {
                                "source": "value"
                            },
                            "enabled": true
                        },
                        "filling_level": {
                            "data": {
                                "payload": "{{payload}}",
                                "payload_function": "getFillingLevel",
                                "payload_type": "source_payload",
                                "resource_stream": "uplink_decoded",
                                "source": "resource_stream"
                            },
                            "default": {
                                "source": "value"
                            },
                            "enabled": true
                        },
                        "latitude": {
                            "data": {
                                "payload": "{{payload}}",
                                "payload_function": "getLatitude",
                                "payload_type": "source_payload",
                                "resource_stream": "uplink_decoded",
                                "source": "resource_stream"
                            },
                            "default": {
                                "source": "value"
                            },
                            "enabled": true
                        },
                        "longitude": {
                            "data": {
                                "payload": "{{payload}}",
                                "payload_function": "getLongitude",
                                "payload_type": "source_payload",
                                "resource_stream": "uplink_decoded",
                                "source": "resource_stream"
                            },
                            "default": {
                                "source": "value"
                            },
                            "enabled": true
                        },
                        "proximity": {
                            "data": {
                                "payload": "{{payload}}",
                                "payload_function": "getProximity",
                                "payload_type": "source_payload",
                                "resource_stream": "uplink_decoded",
                                "source": "resource_stream"
                            },
                            "default": {
                                "source": "value"
                            },
                            "enabled": true
                        },
                        "serial_number": {
                            "data": {
                                "payload": "{{payload}}",
                                "payload_function": "getSerialNumber",
                                "payload_type": "source_payload",
                                "resource_stream": "uplink_decoded",
                                "source": "resource_stream"
                            },
                            "default": {
                                "source": "value"
                            },
                            "enabled": true
                        },
                        "temperature": {
                            "data": {
                                "payload": "{{payload}}",
                                "payload_function": "getTemperature",
                                "payload_type": "source_payload",
                                "resource_stream": "uplink_decoded",
                                "source": "resource_stream"
                            },
                            "default": {
                                "source": "value"
                            },
                            "enabled": true
                        },
                        "uplink": {
                            "data": {
                                "payload": "{{payload}}",
                                "payload_function": "",
                                "payload_type": "source_payload",
                                "resource": "uplink",
                                "source": "resource",
                                "update": "events"
                            },
                            "default": {
                                "source": "value"
                            },
                            "description": "Last raw uplink",
                            "enabled": true
                        },
                        "water_body_level": {
                            "data": {
                                "payload": "{{payload}}",
                                "payload_function": "getWaterBodyLevel",
                                "payload_type": "source_payload",
                                "resource_stream": "uplink_decoded",
                                "source": "resource_stream"
                            },
                            "default": {
                                "source": "value"
                            },
                            "enabled": true
                        }
                    }
                },
                "_resources": {
                    "properties": [
                        {
                            "property": "dashboard",
                            "value": {
                                "name": "Pepperl_fuchs",
                                "placeholders": {
                                    "sources": []
                                },
                                "tabs": [
                                    {
                                        "name": "Main",
                                        "widgets": [
                                            {
                                                "layout": {
                                                    "col": 0,
                                                    "row": 0,
                                                    "sizeX": 4,
                                                    "sizeY": 10
                                                },
                                                "panel": {
                                                    "color": "#ffffff",
                                                    "currentColor": "#ffffff",
                                                    "showOffline": {
                                                        "type": "last_sample"
                                                    },
                                                    "title": "Location Map"
                                                },
                                                "properties": {
                                                    "center": [
                                                        0,
                                                        0
                                                    ],
                                                    "mapType": "roadmap",
                                                    "mode": "geojson",
                                                    "zoom": 15
                                                },
                                                "sources": [
                                                    {
                                                        "bucket": {
                                                            "backend": "mongodb",
                                                            "id": "pepperl_fuchs_wilsen_sonic_level_data",
                                                            "mapping": "location",
                                                            "tags": {
                                                                "device": [],
                                                                "group": []
                                                            }
                                                        },
                                                        "color": "#3498db",
                                                        "name": "Device Location",
                                                        "source": "bucket",
                                                        "timespan": {
                                                            "mode": "latest"
                                                        }
                                                    }
                                                ],
                                                "type": "map"
                                            },
                                            {
                                                "layout": {
                                                    "col": 4,
                                                    "row": 10,
                                                    "sizeX": 2,
                                                    "sizeY": 5
                                                },
                                                "panel": {
                                                    "color": "#ffffff",
                                                    "currentColor": "#ffffff",
                                                    "showOffline": {
                                                        "type": "none"
                                                    },
                                                    "title": "Filling Level"
                                                },
                                                "properties": {
                                                    "color": "#3498db",
                                                    "max": 100,
                                                    "min": 0,
                                                    "unit": "%"
                                                },
                                                "sources": [
                                                    {
                                                        "bucket": {
                                                            "backend": "mongodb",
                                                            "id": "pepperl_fuchs_wilsen_sonic_level_data",
                                                            "mapping": "fillinglvl",
                                                            "tags": {
                                                                "device": [],
                                                                "group": []
                                                            }
                                                        },
                                                        "color": "#3498db",
                                                        "name": "Source 1",
                                                        "source": "bucket",
                                                        "timespan": {
                                                            "mode": "latest"
                                                        }
                                                    }
                                                ],
                                                "type": "donutchart"
                                            },
                                            {
                                                "layout": {
                                                    "col": 0,
                                                    "row": 10,
                                                    "sizeX": 1,
                                                    "sizeY": 5
                                                },
                                                "panel": {
                                                    "color": "#ffffff",
                                                    "currentColor": "#ffffff",
                                                    "showOffline": {
                                                        "type": "none"
                                                    },
                                                    "title": "Proximity"
                                                },
                                                "properties": {
                                                    "color": "#1abc9c",
                                                    "max": 5000,
                                                    "min": 0,
                                                    "unit": "mm"
                                                },
                                                "sources": [
                                                    {
                                                        "bucket": {
                                                            "backend": "mongodb",
                                                            "id": "pepperl_fuchs_wilsen_sonic_level_data",
                                                            "mapping": "proxx_mm",
                                                            "tags": {
                                                                "device": [],
                                                                "group": []
                                                            }
                                                        },
                                                        "color": "#1abc9c",
                                                        "name": "Source 1",
                                                        "source": "bucket",
                                                        "timespan": {
                                                            "mode": "latest"
                                                        }
                                                    }
                                                ],
                                                "type": "donutchart"
                                            },
                                            {
                                                "layout": {
                                                    "col": 2,
                                                    "row": 10,
                                                    "sizeX": 2,
                                                    "sizeY": 5
                                                },
                                                "panel": {
                                                    "color": "#ffffff",
                                                    "currentColor": "#ffffff",
                                                    "showOffline": {
                                                        "type": "none"
                                                    },
                                                    "title": "Temperature"
                                                },
                                                "properties": {
                                                    "color": "#e74c3c",
                                                    "max": 60,
                                                    "min": -20,
                                                    "unit": "°C"
                                                },
                                                "sources": [
                                                    {
                                                        "bucket": {
                                                            "backend": "mongodb",
                                                            "id": "pepperl_fuchs_wilsen_sonic_level_data",
                                                            "mapping": "temp",
                                                            "tags": {
                                                                "device": [],
                                                                "group": []
                                                            }
                                                        },
                                                        "color": "#e74c3c",
                                                        "name": "Source 1",
                                                        "source": "bucket",
                                                        "timespan": {
                                                            "mode": "latest"
                                                        }
                                                    }
                                                ],
                                                "type": "donutchart"
                                            },
                                            {
                                                "layout": {
                                                    "col": 0,
                                                    "row": 15,
                                                    "sizeX": 3,
                                                    "sizeY": 12
                                                },
                                                "panel": {
                                                    "color": "#ffffff",
                                                    "currentColor": "#ffffff",
                                                    "showOffline": {
                                                        "type": "none"
                                                    },
                                                    "title": "Historic Proximity & Filling Level"
                                                },
                                                "properties": {
                                                    "axis": true,
                                                    "fill": false,
                                                    "legend": true,
                                                    "multiple_axes": true
                                                },
                                                "sources": [
                                                    {
                                                        "bucket": {
                                                            "backend": "mongodb",
                                                            "id": "pepperl_fuchs_wilsen_sonic_level_data",
                                                            "mapping": "proxx_mm",
                                                            "tags": {
                                                                "device": [],
                                                                "group": []
                                                            }
                                                        },
                                                        "color": "#1abc9c",
                                                        "name": "Proximity (mm)",
                                                        "source": "bucket",
                                                        "timespan": {
                                                            "magnitude": "hour",
                                                            "mode": "relative",
                                                            "period": "latest",
                                                            "value": 24
                                                        }
                                                    },
                                                    {
                                                        "bucket": {
                                                            "backend": "mongodb",
                                                            "id": "pepperl_fuchs_wilsen_sonic_level_data",
                                                            "mapping": "fillinglvl",
                                                            "tags": {
                                                                "device": [],
                                                                "group": []
                                                            }
                                                        },
                                                        "color": "#3498db",
                                                        "name": "Filling Level (%)",
                                                        "source": "bucket",
                                                        "timespan": {
                                                            "magnitude": "hour",
                                                            "mode": "relative",
                                                            "period": "latest",
                                                            "value": 24
                                                        }
                                                    }
                                                ],
                                                "type": "chart"
                                            },
                                            {
                                                "layout": {
                                                    "col": 3,
                                                    "row": 15,
                                                    "sizeX": 3,
                                                    "sizeY": 12
                                                },
                                                "panel": {
                                                    "color": "#ffffff",
                                                    "currentColor": "#ffffff",
                                                    "showOffline": {
                                                        "type": "none"
                                                    },
                                                    "title": "Last Recorded Data"
                                                },
                                                "properties": {
                                                    "source": "code",
                                                    "template": "<div style=\"width:100%; height:100%; overflow-y:auto\">\r\n  <table class=\"table table-striped table-condensed\">\r\n    <thead>\r\n      <tr>\r\n        <th>Date</th>\r\n        <th>Proximity (mm)</th>\r\n        <th>Filling Level (%)</th>\r\n        <th>Temperature (°C)</th>\r\n        <th>Battery (V)</th>\r\n      </tr>\r\n    </thead>\r\n    <tbody>\r\n      <tr ng-repeat=\"entry in value\">\r\n        <td>{{ entry.ts | date:'medium' }}</td>\r\n        <td>{{ entry.proxx_mm || '—' }}</td>\r\n        <td>{{ entry.fillinglvl || '—' }}</td>\r\n        <td>{{ entry.temp || '—' }}</td>\r\n        <td>{{ entry.battery_vol || '—' }}</td>\r\n      </tr>\r\n    </tbody>\r\n  </table>\r\n</div>\r\n"
                                                },
                                                "sources": [
                                                    {
                                                        "aggregation": {},
                                                        "bucket": {
                                                            "backend": "mongodb",
                                                            "id": "pepperl_fuchs_wilsen_sonic_level_data",
                                                            "mapping": "ts",
                                                            "tags": {
                                                                "device": [],
                                                                "group": []
                                                            }
                                                        },
                                                        "color": "#000000",
                                                        "name": "ts",
                                                        "source": "bucket",
                                                        "timespan": {
                                                            "magnitude": "hour",
                                                            "mode": "relative",
                                                            "period": "latest",
                                                            "value": 24
                                                        }
                                                    },
                                                    {
                                                        "aggregation": {},
                                                        "bucket": {
                                                            "backend": "mongodb",
                                                            "id": "pepperl_fuchs_wilsen_sonic_level_data",
                                                            "mapping": "proxx_mm",
                                                            "tags": {
                                                                "device": [],
                                                                "group": []
                                                            }
                                                        },
                                                        "color": "#1abc9c",
                                                        "name": "proximity",
                                                        "source": "bucket",
                                                        "timespan": {
                                                            "magnitude": "hour",
                                                            "mode": "relative",
                                                            "period": "latest",
                                                            "value": 24
                                                        }
                                                    },
                                                    {
                                                        "aggregation": {},
                                                        "bucket": {
                                                            "backend": "mongodb",
                                                            "id": "pepperl_fuchs_wilsen_sonic_level_data",
                                                            "mapping": "fillinglvl",
                                                            "tags": {
                                                                "device": [],
                                                                "group": []
                                                            }
                                                        },
                                                        "color": "#3498db",
                                                        "name": "filling_level",
                                                        "source": "bucket",
                                                        "timespan": {
                                                            "magnitude": "hour",
                                                            "mode": "relative",
                                                            "period": "latest",
                                                            "value": 24
                                                        }
                                                    },
                                                    {
                                                        "aggregation": {},
                                                        "bucket": {
                                                            "backend": "mongodb",
                                                            "id": "pepperl_fuchs_wilsen_sonic_level_data",
                                                            "mapping": "temp",
                                                            "tags": {
                                                                "device": [],
                                                                "group": []
                                                            }
                                                        },
                                                        "color": "#e74c3c",
                                                        "name": "temperature",
                                                        "source": "bucket",
                                                        "timespan": {
                                                            "magnitude": "hour",
                                                            "mode": "relative",
                                                            "period": "latest",
                                                            "value": 24
                                                        }
                                                    },
                                                    {
                                                        "aggregation": {},
                                                        "bucket": {
                                                            "backend": "mongodb",
                                                            "id": "pepperl_fuchs_wilsen_sonic_level_data",
                                                            "mapping": "battery_vol",
                                                            "tags": {
                                                                "device": [],
                                                                "group": []
                                                            }
                                                        },
                                                        "color": "#f39c12",
                                                        "name": "battery",
                                                        "source": "bucket",
                                                        "timespan": {
                                                            "magnitude": "hour",
                                                            "mode": "relative",
                                                            "period": "latest",
                                                            "value": 24
                                                        }
                                                    }
                                                ],
                                                "type": "html_time"
                                            },
                                            {
                                                "layout": {
                                                    "col": 4,
                                                    "row": 0,
                                                    "sizeX": 2,
                                                    "sizeY": 5
                                                },
                                                "panel": {
                                                    "color": "#ffffff",
                                                    "currentColor": "#ffffff",
                                                    "showOffline": {
                                                        "type": "none"
                                                    },
                                                    "title": "Battery"
                                                },
                                                "properties": {
                                                    "color": "#f39c12",
                                                    "max": 4,
                                                    "min": 2,
                                                    "unit": "V"
                                                },
                                                "sources": [
                                                    {
                                                        "bucket": {
                                                            "backend": "mongodb",
                                                            "id": "pepperl_fuchs_wilsen_sonic_level_data",
                                                            "mapping": "battery_vol",
                                                            "tags": {
                                                                "device": [],
                                                                "group": []
                                                            }
                                                        },
                                                        "color": "#f39c12",
                                                        "name": "Source 1",
                                                        "source": "bucket",
                                                        "timespan": {
                                                            "mode": "latest"
                                                        }
                                                    }
                                                ],
                                                "type": "donutchart"
                                            },
                                            {
                                                "layout": {
                                                    "col": 1,
                                                    "row": 10,
                                                    "sizeX": 1,
                                                    "sizeY": 5
                                                },
                                                "panel": {
                                                    "color": "#ffffff",
                                                    "currentColor": "#ffffff",
                                                    "showOffline": {
                                                        "type": "none"
                                                    },
                                                    "title": "Amplitude"
                                                },
                                                "properties": {
                                                    "color": "#9b59b6",
                                                    "max": 100,
                                                    "min": 0,
                                                    "unit": ""
                                                },
                                                "sources": [
                                                    {
                                                        "bucket": {
                                                            "backend": "mongodb",
                                                            "id": "pepperl_fuchs_wilsen_sonic_level_data",
                                                            "mapping": "amplitude",
                                                            "tags": {
                                                                "device": [],
                                                                "group": []
                                                            }
                                                        },
                                                        "color": "#9b59b6",
                                                        "name": "Source 1",
                                                        "source": "bucket",
                                                        "timespan": {
                                                            "mode": "latest"
                                                        }
                                                    }
                                                ],
                                                "type": "donutchart"
                                            },
                                            {
                                                "layout": {
                                                    "col": 4,
                                                    "row": 5,
                                                    "sizeX": 2,
                                                    "sizeY": 5
                                                },
                                                "panel": {
                                                    "color": "#ffffff",
                                                    "currentColor": "#ffffff",
                                                    "showOffline": {
                                                        "type": "none"
                                                    },
                                                    "title": "Water Body Level"
                                                },
                                                "properties": {
                                                    "color": "#16a085",
                                                    "max": 10000,
                                                    "min": 0,
                                                    "unit": "mm"
                                                },
                                                "sources": [
                                                    {
                                                        "bucket": {
                                                            "backend": "mongodb",
                                                            "id": "pepperl_fuchs_wilsen_sonic_level_data",
                                                            "mapping": "water_body_level_mm",
                                                            "tags": {
                                                                "device": [],
                                                                "group": []
                                                            }
                                                        },
                                                        "color": "#16a085",
                                                        "name": "Source 1",
                                                        "source": "bucket",
                                                        "timespan": {
                                                            "mode": "latest"
                                                        }
                                                    }
                                                ],
                                                "type": "donutchart"
                                            }
                                        ]
                                    }
                                ]
                            }
                        }
                    ]
                }
            }
        ]
    }
}