import argparse
import logging
from pathlib import Path
import sys
import time

PYMODBUS_VERSION = "3.12.1"

try:
    from pymodbus.client import ModbusTcpClient
except ImportError:
    print(f"Error: 'pymodbus' module not found. Please install: pip3 install pymodbus=={PYMODBUS_VERSION}")
    sys.exit(1)


logging.basicConfig()
log = logging.getLogger()
log.setLevel(logging.ERROR)

W8004_SENSOR_TYPE = "W8004_thermostat"
AN307_SENSOR_TYPE = "AN_307_sound_light_alarm"
AN201G_SENSOR_TYPE = "AN_201G_vibrating_wire_strain_gauge"
DS501_SENSOR_TYPE = "DS_501_socket"
DS103_SENSOR_TYPE = "DS_103_3ch_switch"
EF5600_SENSOR_TYPE = "EF5600_DN1_electrical_fire_monitor"
_BUILTIN_SNAPSHOT = {'globals': {'http_port': '8070',
             'http_enable': '1',
             'auto_save': '1',
             'save_interval': '60',
             'check_interval': '5',
             'cleanup_threshold_pct': '80',
             'cleanup_delete_pct': '25',
             'sync_enable': '1',
             'sync_interval': '60',
             'default_sensor_type': 'undefine',
             'default_keep_alive_interval': '86400',
             'default_modbus_tcp_enable': '1',
             'default_modbus_tcp_port': '502',
             'default_modbus_tcp_slave_id': '2',
             'default_bacnet_bip_enable': '1',
             'default_bacnet_bip_id': '101',
             'unicast_max_retry': '1',
             'multicast_max_retry': '1',
             'bacnet_instance_number': '260001'},
 'attributes': {'powerState': {'name': 'powerState',
                               'json_key': 'powerState',
                               'data_type': 'bool',
                               'unit': 'none',
                               'readwrite': '1',
                               'description': 'Power on or off',
                               'modbus_enable': '1',
                               'modbus_table': 'holding',
                               'modbus_register_count': '1',
                               'modbus_mapping_mode': 'single',
                               'modbus_scale': '1',
                               'bacnet_enable': '1',
                               'bacnet_object_type': 'BV',
                               'bacnet_unit': '95'},
                'switch': {'name': 'switch',
                           'json_key': 'switch',
                           'data_type': 'bool',
                           'unit': 'none',
                           'readwrite': '1',
                           'description': 'Socket switch on or off',
                           'modbus_enable': '1',
                           'modbus_table': 'holding',
                           'modbus_register_count': '1',
                           'modbus_mapping_mode': 'single',
                           'modbus_scale': '1',
                           'bacnet_enable': '1',
                           'bacnet_object_type': 'BV',
                           'bacnet_unit': '95'},
                'temperature': {'name': 'temperature',
                                'json_key': 'temperature',
                                'data_type': 'float',
                                'unit': 'celsius',
                                'decimal_places': '1',
                                'min_value': '-100',
                                'max_value': '500',
                                'readwrite': '0',
                                'description': 'Temperature',
                                'modbus_enable': '1',
                                'modbus_table': 'holding',
                                'modbus_register_count': '1',
                                'modbus_mapping_mode': 'single',
                                'modbus_scale': '100',
                                'bacnet_enable': '1',
                                'bacnet_object_type': 'AI',
                                'bacnet_unit': '62'},
                'co2': {'name': 'co2',
                        'json_key': 'co2',
                        'data_type': 'int',
                        'unit': 'none',
                        'min_value': '0',
                        'max_value': '65535',
                        'readwrite': '0',
                        'description': 'CO2 concentration',
                        'modbus_enable': '1',
                        'modbus_table': 'holding',
                        'modbus_register_count': '1',
                        'modbus_mapping_mode': 'single',
                        'modbus_scale': '1',
                        'bacnet_enable': '1',
                        'bacnet_object_type': 'AI',
                        'bacnet_unit': '95'},
                'pm25': {'name': 'pm25',
                         'json_key': 'pm25',
                         'data_type': 'int',
                         'unit': 'none',
                         'min_value': '0',
                         'max_value': '65535',
                         'readwrite': '0',
                         'description': 'PM2.5 concentration',
                         'modbus_enable': '1',
                         'modbus_table': 'holding',
                         'modbus_register_count': '1',
                         'modbus_mapping_mode': 'single',
                         'modbus_scale': '1',
                         'bacnet_enable': '1',
                         'bacnet_object_type': 'AI',
                         'bacnet_unit': '95'},
                'formaldehyde': {'name': 'formaldehyde',
                                 'json_key': 'formaldehyde',
                                 'data_type': 'int',
                                 'unit': 'none',
                                 'min_value': '0',
                                 'max_value': '65535',
                                 'readwrite': '0',
                                 'description': 'Formaldehyde concentration',
                                 'modbus_enable': '1',
                                 'modbus_table': 'holding',
                                 'modbus_register_count': '1',
                                 'modbus_mapping_mode': 'single',
                                 'modbus_scale': '1',
                                 'bacnet_enable': '1',
                                 'bacnet_object_type': 'AI',
                                 'bacnet_unit': '95'},
                'tvoc': {'name': 'tvoc',
                         'json_key': 'tvoc',
                         'data_type': 'int',
                         'unit': 'none',
                         'min_value': '0',
                         'max_value': '65535',
                         'readwrite': '0',
                         'description': 'TVOC concentration',
                         'modbus_enable': '1',
                         'modbus_table': 'holding',
                         'modbus_register_count': '1',
                         'modbus_mapping_mode': 'single',
                         'modbus_scale': '1',
                         'bacnet_enable': '1',
                         'bacnet_object_type': 'AI',
                         'bacnet_unit': '95'},
                'humidity': {'name': 'humidity',
                             'json_key': 'humidity',
                             'data_type': 'float',
                             'unit': 'percent',
                             'decimal_places': '1',
                             'min_value': '0',
                             'max_value': '99.9',
                             'readwrite': '0',
                             'description': 'Humidity',
                             'modbus_enable': '1',
                             'modbus_table': 'holding',
                             'modbus_register_count': '1',
                             'modbus_mapping_mode': 'single',
                             'modbus_scale': '100',
                             'bacnet_enable': '1',
                             'bacnet_object_type': 'AI',
                             'bacnet_unit': '98'},
                'bootVersion': {'name': 'bootVersion',
                                'json_key': 'bootVersion',
                                'data_type': 'string',
                                'unit': 'none',
                                'string_max_len': '16',
                                'readwrite': '0',
                                'description': 'Firmware U-boot Version',
                                'modbus_enable': '1',
                                'modbus_table': 'holding',
                                'modbus_register_count': '8',
                                'modbus_mapping_mode': 'string',
                                'modbus_scale': '1',
                                'bacnet_enable': '1',
                                'bacnet_object_type': 'CV',
                                'bacnet_unit': '95'},
                'mainVersion': {'name': 'mainVersion',
                                'json_key': 'mainVersion',
                                'data_type': 'string',
                                'unit': 'none',
                                'string_max_len': '16',
                                'readwrite': '0',
                                'description': 'Firmware Main Version',
                                'modbus_enable': '1',
                                'modbus_table': 'holding',
                                'modbus_register_count': '8',
                                'modbus_mapping_mode': 'string',
                                'modbus_scale': '1',
                                'bacnet_enable': '1',
                                'bacnet_object_type': 'CV',
                                'bacnet_unit': '95'},
                'appVersion': {'name': 'appVersion',
                               'json_key': 'appVersion',
                               'data_type': 'string',
                               'unit': 'none',
                               'string_max_len': '16',
                               'readwrite': '0',
                               'description': 'Firmware Application Version',
                               'modbus_enable': '1',
                               'modbus_table': 'holding',
                               'modbus_register_count': '8',
                               'modbus_mapping_mode': 'string',
                               'modbus_scale': '1',
                               'bacnet_enable': '1',
                               'bacnet_object_type': 'CV',
                               'bacnet_unit': '95'},
                'hardwareVersion': {'name': 'hardwareVersion',
                                    'json_key': 'hardwareVersion',
                                    'data_type': 'string',
                                    'unit': 'none',
                                    'string_max_len': '16',
                                    'readwrite': '0',
                                    'description': 'Hardware Version',
                                    'modbus_enable': '1',
                                    'modbus_table': 'holding',
                                    'modbus_register_count': '8',
                                    'modbus_mapping_mode': 'string',
                                    'modbus_scale': '1',
                                    'bacnet_enable': '1',
                                    'bacnet_object_type': 'CV',
                                    'bacnet_unit': '95'},
                'model': {'name': 'model',
                          'json_key': 'model',
                          'data_type': 'string',
                          'unit': 'none',
                          'string_max_len': '24',
                          'readwrite': '0',
                          'description': 'Product Model',
                          'modbus_enable': '1',
                          'modbus_table': 'holding',
                          'modbus_register_count': '12',
                          'modbus_mapping_mode': 'string',
                          'modbus_scale': '1',
                          'bacnet_enable': '1',
                          'bacnet_object_type': 'CV',
                          'bacnet_unit': '95'},
                'batteryVoltage': {'name': 'batteryVoltage',
                                   'json_key': 'batteryVoltage',
                                   'data_type': 'float',
                                   'unit': 'volt',
                                   'decimal_places': '2',
                                   'min_value': '0.1',
                                   'max_value': '48.0',
                                   'readwrite': '0',
                                   'description': 'Battery Voltage',
                                   'modbus_enable': '1',
                                   'modbus_table': 'holding',
                                   'modbus_register_count': '1',
                                   'modbus_mapping_mode': 'single',
                                   'modbus_scale': '100',
                                   'bacnet_enable': '1',
                                   'bacnet_object_type': 'AI',
                                   'bacnet_unit': '5'},
                'batteryVoltageState': {'name': 'batteryVoltageState',
                                        'json_key': 'batteryVoltageState',
                                        'data_type': 'int',
                                        'unit': 'none',
                                        'min_value': '0',
                                        'max_value': '10',
                                        'readwrite': '0',
                                        'description': 'Battery State',
                                        'modbus_enable': '1',
                                        'modbus_table': 'holding',
                                        'modbus_register_count': '1',
                                        'modbus_mapping_mode': 'single',
                                        'modbus_scale': '1',
                                        'bacnet_enable': '1',
                                        'bacnet_object_type': 'AI',
                                        'bacnet_unit': '95'},
                'batteryLevel': {'name': 'batteryLevel',
                                 'json_key': 'batteryLevel',
                                 'data_type': 'int',
                                 'unit': 'percent',
                                 'min_value': '0',
                                 'max_value': '100',
                                 'readwrite': '0',
                                 'description': 'Battery level',
                                 'modbus_enable': '1',
                                 'modbus_table': 'holding',
                                 'modbus_register_count': '1',
                                 'modbus_mapping_mode': 'single',
                                 'modbus_scale': '1',
                                 'bacnet_enable': '1',
                                 'bacnet_object_type': 'AI',
                                 'bacnet_unit': '98'},
                'online': {'name': 'online',
                           'json_key': 'online',
                           'data_type': 'bool',
                           'unit': 'none',
                           'readwrite': '0',
                           'description': 'Online Status',
                           'modbus_enable': '1',
                           'modbus_table': 'holding',
                           'modbus_register_count': '1',
                           'modbus_mapping_mode': 'single',
                           'modbus_scale': '1',
                           'bacnet_enable': '1',
                           'bacnet_object_type': 'BI',
                           'bacnet_unit': '95'},
                'lastOnlineTime': {'name': 'lastOnlineTime',
                                   'json_key': 'lastOnlineTime',
                                   'data_type': 'timestamp',
                                   'unit': 'second',
                                   'readwrite': '0',
                                   'description': 'Last Online Time (Unix timestamp)',
                                   'modbus_enable': '1',
                                   'modbus_table': 'holding',
                                   'modbus_register_count': '2',
                                   'modbus_mapping_mode': 'big_endian',
                                   'modbus_scale': '1',
                                   'bacnet_enable': '1',
                                   'bacnet_object_type': 'AI',
                                   'bacnet_unit': '73'},
                'doorState': {'name': 'doorState',
                              'json_key': 'doorState',
                              'data_type': 'int',
                              'unit': 'none',
                              'min_value': '0',
                              'max_value': '1',
                              'readwrite': '0',
                              'description': 'door open(1)/close(0)',
                              'modbus_enable': '1',
                              'modbus_table': 'holding',
                              'modbus_register_count': '1',
                              'modbus_mapping_mode': 'single',
                              'modbus_scale': '1',
                              'bacnet_enable': '1',
                              'bacnet_object_type': 'BI',
                              'bacnet_unit': '95'},
                'levelValue': {'name': 'levelValue',
                               'json_key': 'levelValue',
                               'data_type': 'float',
                               'unit': 'percent',
                               'decimal_places': '1',
                               'min_value': '0',
                               'max_value': '100',
                               'readwrite': '0',
                               'description': 'liquid level percent',
                               'modbus_enable': '1',
                               'modbus_table': 'holding',
                               'modbus_register_count': '1',
                               'modbus_mapping_mode': 'single',
                               'modbus_scale': '10',
                               'bacnet_enable': '1',
                               'bacnet_object_type': 'AI',
                               'bacnet_unit': '98'},
                'presence': {'name': 'presence',
                             'json_key': 'presence',
                             'data_type': 'bool',
                             'unit': 'none',
                             'readwrite': '0',
                             'description': 'presence detection',
                             'modbus_enable': '1',
                             'modbus_table': 'holding',
                             'modbus_register_count': '1',
                             'modbus_mapping_mode': 'single',
                             'modbus_scale': '1',
                             'bacnet_enable': '1',
                             'bacnet_object_type': 'BI',
                             'bacnet_unit': '95'},
                'distance': {'name': 'distance',
                             'json_key': 'distance',
                             'data_type': 'float',
                             'unit': 'meter',
                             'decimal_places': '2',
                             'min_value': '0',
                             'max_value': '100',
                             'readwrite': '0',
                             'description': 'Target Distance',
                             'modbus_enable': '1',
                             'modbus_table': 'holding',
                             'modbus_register_count': '1',
                             'modbus_mapping_mode': 'single',
                             'modbus_scale': '100',
                             'bacnet_enable': '1',
                             'bacnet_object_type': 'AI',
                             'bacnet_unit': '31'},
                'lastPayload': {'name': 'lastPayload',
                                'json_key': 'lastPayload',
                                'data_type': 'binary',
                                'unit': 'none',
                                'readwrite': '0',
                                'description': 'Last Payload Data',
                                'modbus_enable': '1',
                                'modbus_table': 'holding',
                                'modbus_register_count': '130',
                                'modbus_mapping_mode': 'binary',
                                'modbus_scale': '1',
                                'bacnet_enable': '1',
                                'bacnet_object_type': 'CV',
                                'bacnet_unit': '95'},
                'lastPayloadLen': {'name': 'lastPayloadLen',
                                   'json_key': 'lastPayloadLen',
                                   'data_type': 'int',
                                   'unit': 'none',
                                   'min_value': '0',
                                   'max_value': '256',
                                   'description': 'Last Payload Length',
                                   'modbus_enable': '1',
                                   'modbus_table': 'holding',
                                   'modbus_register_count': '1',
                                   'modbus_mapping_mode': 'single',
                                   'modbus_scale': '1',
                                   'bacnet_enable': '1',
                                   'bacnet_object_type': 'AI',
                                   'bacnet_unit': '95'},
                'lastFport': {'name': 'lastFport',
                              'json_key': 'lastFport',
                              'data_type': 'int',
                              'unit': 'none',
                              'min_value': '0',
                              'max_value': '256',
                              'description': 'Last FPort Used',
                              'modbus_enable': '1',
                              'modbus_table': 'holding',
                              'modbus_register_count': '1',
                              'modbus_mapping_mode': 'single',
                              'modbus_scale': '1',
                              'bacnet_enable': '1',
                              'bacnet_object_type': 'AI',
                              'bacnet_unit': '95'},
                'tamper': {'name': 'tamper',
                           'json_key': 'tamper',
                           'data_type': 'int',
                           'unit': 'none',
                           'min_value': '0',
                           'max_value': '2',
                           'description': 'Tamper Detection',
                           'modbus_enable': '1',
                           'modbus_table': 'holding',
                           'modbus_register_count': '1',
                           'modbus_mapping_mode': 'single',
                           'modbus_scale': '1',
                           'bacnet_enable': '1',
                           'bacnet_object_type': 'AI',
                           'bacnet_unit': '95'},
                'tamperEvent': {'name': 'tamperEvent',
                                'json_key': 'tamperEvent',
                                'data_type': 'int',
                                'unit': 'none',
                                'min_value': '0',
                                'max_value': '2',
                                'description': 'Tamper Detection Event',
                                'modbus_enable': '1',
                                'modbus_table': 'holding',
                                'modbus_register_count': '1',
                                'modbus_mapping_mode': 'single',
                                'modbus_scale': '1',
                                'bacnet_enable': '1',
                                'bacnet_object_type': 'AI',
                                'bacnet_unit': '95'},
                'infraredEvent': {'name': 'infraredEvent',
                                  'json_key': 'infraredEvent',
                                  'data_type': 'int',
                                  'unit': 'none',
                                  'readwrite': '0',
                                  'min_value': '0',
                                  'max_value': '255',
                                  'description': 'Infrared detection event code',
                                  'modbus_enable': '1',
                                  'modbus_table': 'holding',
                                  'modbus_register_count': '1',
                                  'modbus_mapping_mode': 'single',
                                  'modbus_scale': '1',
                                  'bacnet_enable': '1',
                                  'bacnet_object_type': 'AI',
                                  'bacnet_unit': '95'},
                'temperatureState': {'name': 'temperatureState',
                                     'json_key': 'temperatureState',
                                     'data_type': 'int',
                                     'unit': 'none',
                                     'min_value': '0',
                                     'max_value': '2',
                                     'readwrite': '0',
                                     'description': 'Temperature State',
                                     'modbus_enable': '1',
                                     'modbus_table': 'holding',
                                     'modbus_register_count': '1',
                                     'modbus_mapping_mode': 'single',
                                     'modbus_scale': '1',
                                     'bacnet_enable': '1',
                                     'bacnet_object_type': 'AI',
                                     'bacnet_unit': '95'},
                'humidityState': {'name': 'humidityState',
                                  'json_key': 'humidityState',
                                  'data_type': 'int',
                                  'unit': 'none',
                                  'min_value': '0',
                                  'max_value': '2',
                                  'readwrite': '0',
                                  'description': 'Humidity State',
                                  'modbus_enable': '1',
                                  'modbus_table': 'holding',
                                  'modbus_register_count': '1',
                                  'modbus_mapping_mode': 'single',
                                  'modbus_scale': '1',
                                  'bacnet_enable': '1',
                                  'bacnet_object_type': 'AI',
                                  'bacnet_unit': '95'},
                'snr': {'name': 'snr',
                        'json_key': 'snr',
                        'data_type': 'int',
                        'unit': 'none',
                        'min_value': '-128',
                        'max_value': '128',
                        'readwrite': '0',
                        'description': 'SNR (dB)',
                        'modbus_enable': '1',
                        'modbus_table': 'holding',
                        'modbus_register_count': '1',
                        'modbus_mapping_mode': 'single',
                        'modbus_scale': '1',
                        'bacnet_enable': '1',
                        'bacnet_object_type': 'AI',
                        'bacnet_unit': '95'},
                'ef5600CommandCode': {'name': 'ef5600CommandCode',
                                      'json_key': 'ef5600CommandCode',
                                      'data_type': 'int',
                                      'unit': 'none',
                                      'min_value': '0',
                                      'max_value': '255',
                                      'readwrite': '1',
                                      'description': 'EF5600 Command Code',
                                      'modbus_enable': '1',
                                      'modbus_table': 'holding',
                                      'modbus_register_count': '1',
                                      'modbus_mapping_mode': 'single',
                                      'modbus_scale': '1',
                                      'bacnet_enable': '1',
                                      'bacnet_object_type': 'AV',
                                      'bacnet_unit': '95'},
                'ef5600SettingAddress': {'name': 'ef5600SettingAddress',
                                         'json_key': 'ef5600SettingAddress',
                                         'data_type': 'int',
                                         'unit': 'none',
                                         'min_value': '0',
                                         'max_value': '65535',
                                         'readwrite': '1',
                                         'description': 'EF5600 Setting Address',
                                         'modbus_enable': '1',
                                         'modbus_table': 'holding',
                                         'modbus_register_count': '1',
                                         'modbus_mapping_mode': 'single',
                                         'modbus_scale': '1',
                                         'bacnet_enable': '1',
                                         'bacnet_object_type': 'AV',
                                         'bacnet_unit': '95'},
                'ef5600SettingValueHigh': {'name': 'ef5600SettingValueHigh',
                                           'json_key': 'ef5600SettingValueHigh',
                                           'data_type': 'int',
                                           'unit': 'none',
                                           'min_value': '0',
                                           'max_value': '255',
                                           'readwrite': '1',
                                           'description': 'EF5600 Setting Value High Byte',
                                           'modbus_enable': '1',
                                           'modbus_table': 'holding',
                                           'modbus_register_count': '1',
                                           'modbus_mapping_mode': 'single',
                                           'modbus_scale': '1',
                                           'bacnet_enable': '1',
                                           'bacnet_object_type': 'AV',
                                           'bacnet_unit': '95'},
                'ef5600SettingValueLow': {'name': 'ef5600SettingValueLow',
                                          'json_key': 'ef5600SettingValueLow',
                                          'data_type': 'int',
                                          'unit': 'none',
                                          'min_value': '0',
                                          'max_value': '255',
                                          'readwrite': '1',
                                          'description': 'EF5600 Setting Value Low Byte',
                                          'modbus_enable': '1',
                                          'modbus_table': 'holding',
                                          'modbus_register_count': '1',
                                          'modbus_mapping_mode': 'single',
                                          'modbus_scale': '1',
                                          'bacnet_enable': '1',
                                          'bacnet_object_type': 'AV',
                                          'bacnet_unit': '95'},
                'rssi': {'name': 'rssi',
                         'json_key': 'rssi',
                         'data_type': 'int',
                         'unit': 'none',
                         'min_value': '-128',
                         'max_value': '128',
                         'readwrite': '0',
                         'description': 'RSSI (dBm)',
                         'modbus_enable': '1',
                         'modbus_table': 'holding',
                         'modbus_register_count': '1',
                         'modbus_mapping_mode': 'single',
                         'modbus_scale': '1',
                         'bacnet_enable': '1',
                         'bacnet_object_type': 'AI',
                         'bacnet_unit': '95'},
                'setTemperature': {'name': 'setTemperature',
                                   'json_key': 'setTemperature',
                                   'data_type': 'float',
                                   'unit': 'celsius',
                                   'decimal_places': '1',
                                   'min_value': '10',
                                   'max_value': '35',
                                   'readwrite': '1',
                                   'description': 'Set Temperature',
                                   'modbus_enable': '1',
                                   'modbus_table': 'holding',
                                   'modbus_register_count': '1',
                                   'modbus_mapping_mode': 'single',
                                   'modbus_scale': '100',
                                   'bacnet_enable': '1',
                                   'bacnet_object_type': 'AV',
                                   'bacnet_unit': '62'},
                'workMode': {'name': 'workMode',
                             'json_key': 'workMode',
                             'data_type': 'int',
                             'unit': 'none',
                             'min_value': '0',
                             'max_value': '3',
                             'readwrite': '1',
                             'description': 'Work Mode (0:auto, 1:cool, 2:heat, 3:vent)',
                             'modbus_enable': '1',
                             'modbus_table': 'holding',
                             'modbus_register_count': '1',
                             'modbus_mapping_mode': 'single',
                             'modbus_scale': '1',
                             'bacnet_enable': '1',
                             'bacnet_object_type': 'AV',
                             'bacnet_unit': '95'},
                'fanSpeed': {'name': 'fanSpeed',
                             'json_key': 'fanSpeed',
                             'data_type': 'int',
                             'unit': 'none',
                             'min_value': '0',
                             'max_value': '4',
                             'readwrite': '1',
                             'description': 'Fan Speed (0:off, 1:low, 2:mid, 3:high, 4:auto)',
                             'modbus_enable': '1',
                             'modbus_table': 'holding',
                             'modbus_register_count': '1',
                             'modbus_mapping_mode': 'single',
                             'modbus_scale': '1',
                             'bacnet_enable': '1',
                             'bacnet_object_type': 'AV',
                             'bacnet_unit': '95'},
                'keyLockState': {'name': 'keyLockState',
                                 'json_key': 'keyLockState',
                                 'data_type': 'int',
                                 'unit': 'none',
                                 'min_value': '0',
                                 'max_value': '1',
                                 'readwrite': '1',
                                 'description': 'Key Lock State (0:unlocked, 1:locked)',
                                 'modbus_enable': '1',
                                 'modbus_table': 'holding',
                                 'modbus_register_count': '1',
                                 'modbus_mapping_mode': 'single',
                                 'modbus_scale': '1',
                                 'bacnet_enable': '1',
                                 'bacnet_object_type': 'BV',
                                 'bacnet_unit': '95'},
                'valveState': {'name': 'valveState',
                               'json_key': 'valveState',
                               'data_type': 'int',
                               'unit': 'none',
                               'min_value': '0',
                               'max_value': '1',
                               'readwrite': '0',
                               'description': 'Valve State (0:closed, 1:open)',
                               'modbus_enable': '1',
                               'modbus_table': 'holding',
                               'modbus_register_count': '1',
                               'modbus_mapping_mode': 'single',
                               'modbus_scale': '1',
                               'bacnet_enable': '1',
                               'bacnet_object_type': 'BI',
                               'bacnet_unit': '95'},
                'signalStrength': {'name': 'signalStrength',
                                   'json_key': 'signalStrength',
                                   'data_type': 'int',
                                   'unit': 'none',
                                   'min_value': '0',
                                   'max_value': '3',
                                   'readwrite': '1',
                                   'description': 'Wireless Signal Strength (0:offline, 1:poor, 2:good, 3:excellent)',
                                   'modbus_enable': '1',
                                   'modbus_table': 'holding',
                                   'modbus_register_count': '1',
                                   'modbus_mapping_mode': 'single',
                                   'modbus_scale': '1',
                                   'bacnet_enable': '1',
                                   'bacnet_object_type': 'AI',
                                   'bacnet_unit': '95'},
                'cumulativeOnTime': {'name': 'cumulativeOnTime',
                                     'json_key': 'cumulativeOnTime',
                                     'data_type': 'int',
                                     'unit': 'minute',
                                     'min_value': '0',
                                     'max_value': '999999',
                                     'readwrite': '0',
                                     'description': 'Cumulative Power-On Time',
                                     'modbus_enable': '1',
                                     'modbus_table': 'holding',
                                     'modbus_register_count': '1',
                                     'modbus_mapping_mode': 'single',
                                     'modbus_scale': '10',
                                     'bacnet_enable': '1',
                                     'bacnet_object_type': 'AI',
                                     'bacnet_unit': '73'},
                'cumulativeValveOpenTime': {'name': 'cumulativeValveOpenTime',
                                            'json_key': 'cumulativeValveOpenTime',
                                            'data_type': 'int',
                                            'unit': 'minute',
                                            'min_value': '0',
                                            'max_value': '999999',
                                            'readwrite': '0',
                                            'description': 'Cumulative Valve Open Time',
                                            'modbus_enable': '1',
                                            'modbus_table': 'holding',
                                            'modbus_register_count': '1',
                                            'modbus_mapping_mode': 'single',
                                            'modbus_scale': '10',
                                            'bacnet_enable': '1',
                                            'bacnet_object_type': 'AI',
                                            'bacnet_unit': '73'},
                'voltage': {'name': 'voltage',
                            'json_key': 'voltage',
                            'data_type': 'float',
                            'unit': 'volt',
                            'decimal_places': '1',
                            'min_value': '0',
                            'max_value': '300',
                            'readwrite': '0',
                            'description': 'Voltage (RMS)',
                            'modbus_enable': '1',
                            'modbus_table': 'holding',
                            'modbus_register_count': '1',
                            'modbus_mapping_mode': 'single',
                            'modbus_scale': '10',
                            'bacnet_enable': '1',
                            'bacnet_object_type': 'AI',
                            'bacnet_unit': '5'},
                'current': {'name': 'current',
                            'json_key': 'current',
                            'data_type': 'float',
                            'unit': 'ampere',
                            'decimal_places': '2',
                            'min_value': '0',
                            'max_value': '20',
                            'readwrite': '0',
                            'description': 'Current (RMS)',
                            'modbus_enable': '1',
                            'modbus_table': 'holding',
                            'modbus_register_count': '1',
                            'modbus_mapping_mode': 'single',
                            'modbus_scale': '100',
                            'bacnet_enable': '1',
                            'bacnet_object_type': 'AI',
                            'bacnet_unit': '8'},
                'activePower': {'name': 'activePower',
                                'json_key': 'activePower',
                                'data_type': 'float',
                                'unit': 'watt',
                                'decimal_places': '2',
                                'min_value': '0',
                                'max_value': '3500',
                                'readwrite': '0',
                                'description': 'Active Power',
                                'modbus_enable': '1',
                                'modbus_table': 'holding',
                                'modbus_register_count': '1',
                                'modbus_mapping_mode': 'single',
                                'modbus_scale': '100',
                                'bacnet_enable': '1',
                                'bacnet_object_type': 'AI',
                                'bacnet_unit': '29'},
                'energy': {'name': 'energy',
                           'json_key': 'energy',
                           'data_type': 'float',
                           'unit': 'kilowatt_hour',
                           'decimal_places': '2',
                           'min_value': '0',
                           'max_value': '999999',
                           'readwrite': '0',
                           'description': 'Energy Consumption',
                           'modbus_enable': '1',
                           'modbus_table': 'holding',
                           'modbus_register_count': '2',
                           'modbus_mapping_mode': 'big_endian',
                           'modbus_scale': '100',
                           'bacnet_enable': '1',
                           'bacnet_object_type': 'AI',
                           'bacnet_unit': '30'},
                'lockState': {'name': 'lockState',
                              'json_key': 'lockState',
                              'data_type': 'int',
                              'unit': 'none',
                              'min_value': '0',
                              'max_value': '1',
                              'readwrite': '1',
                              'description': 'Socket Lock State (0:unlocked, 1:locked)',
                              'modbus_enable': '1',
                              'modbus_table': 'holding',
                              'modbus_register_count': '1',
                              'modbus_mapping_mode': 'single',
                              'modbus_scale': '1',
                              'bacnet_enable': '1',
                              'bacnet_object_type': 'BV',
                              'bacnet_unit': '95'},
                'timerCloseEnabled': {'name': 'timerCloseEnabled',
                                      'json_key': 'timerCloseEnabled',
                                      'data_type': 'bool',
                                      'unit': 'none',
                                      'readwrite': '0',
                                      'description': 'Timer Close Enabled',
                                      'modbus_enable': '1',
                                      'modbus_table': 'holding',
                                      'modbus_register_count': '1',
                                      'modbus_mapping_mode': 'single',
                                      'modbus_scale': '1',
                                      'bacnet_enable': '1',
                                      'bacnet_object_type': 'BI',
                                      'bacnet_unit': '95'},
                'timerOpenEnabled': {'name': 'timerOpenEnabled',
                                     'json_key': 'timerOpenEnabled',
                                     'data_type': 'bool',
                                     'unit': 'none',
                                     'readwrite': '0',
                                     'description': 'Timer Open Enabled',
                                     'modbus_enable': '1',
                                     'modbus_table': 'holding',
                                     'modbus_register_count': '1',
                                     'modbus_mapping_mode': 'single',
                                     'modbus_scale': '1',
                                     'bacnet_enable': '1',
                                     'bacnet_object_type': 'BI',
                                     'bacnet_unit': '95'},
                'timerLockEnabled': {'name': 'timerLockEnabled',
                                     'json_key': 'timerLockEnabled',
                                     'data_type': 'bool',
                                     'unit': 'none',
                                     'readwrite': '0',
                                     'description': 'Timer Lock Enabled',
                                     'modbus_enable': '1',
                                     'modbus_table': 'holding',
                                     'modbus_register_count': '1',
                                     'modbus_mapping_mode': 'single',
                                     'modbus_scale': '1',
                                     'bacnet_enable': '1',
                                     'bacnet_object_type': 'BI',
                                     'bacnet_unit': '95'},
                'timerUnlockEnabled': {'name': 'timerUnlockEnabled',
                                       'json_key': 'timerUnlockEnabled',
                                       'data_type': 'bool',
                                       'unit': 'none',
                                       'readwrite': '0',
                                       'description': 'Timer Unlock Enabled',
                                       'modbus_enable': '1',
                                       'modbus_table': 'holding',
                                       'modbus_register_count': '1',
                                       'modbus_mapping_mode': 'single',
                                       'modbus_scale': '1',
                                       'bacnet_enable': '1',
                                       'bacnet_object_type': 'BI',
                                       'bacnet_unit': '95'},
                'waterStatus': {'name': 'waterStatus',
                                'json_key': 'waterStatus',
                                'data_type': 'bool',
                                'unit': 'none',
                                'readwrite': '0',
                                'description': 'Water Leakage Status (true=water detected)',
                                'modbus_enable': '1',
                                'modbus_table': 'holding',
                                'modbus_register_count': '1',
                                'modbus_mapping_mode': 'single',
                                'modbus_scale': '1',
                                'bacnet_enable': '1',
                                'bacnet_object_type': 'BI',
                                'bacnet_unit': '95'},
                'waterDuration': {'name': 'waterDuration',
                                  'json_key': 'waterDuration',
                                  'data_type': 'int',
                                  'unit': 'minute',
                                  'min_value': '0',
                                  'max_value': '65535',
                                  'readwrite': '0',
                                  'description': 'Water Leakage Duration (minutes)',
                                  'modbus_enable': '1',
                                  'modbus_table': 'holding',
                                  'modbus_register_count': '1',
                                  'modbus_mapping_mode': 'single',
                                  'modbus_scale': '1',
                                  'bacnet_enable': '1',
                                  'bacnet_object_type': 'AI',
                                  'bacnet_unit': '73'},
                'batteryLowEvent': {'name': 'batteryLowEvent',
                                    'json_key': 'batteryLowEvent',
                                    'data_type': 'bool',
                                    'unit': 'none',
                                    'readwrite': '0',
                                    'description': 'Battery Low Voltage Event',
                                    'modbus_enable': '1',
                                    'modbus_table': 'holding',
                                    'modbus_register_count': '1',
                                    'modbus_mapping_mode': 'single',
                                    'modbus_scale': '1',
                                    'bacnet_enable': '1',
                                    'bacnet_object_type': 'BI',
                                    'bacnet_unit': '95'},
                'waterEvent': {'name': 'waterEvent',
                               'json_key': 'waterEvent',
                               'data_type': 'bool',
                               'unit': 'none',
                               'readwrite': '0',
                               'description': 'Water Leakage Event',
                               'modbus_enable': '1',
                               'modbus_table': 'holding',
                               'modbus_register_count': '1',
                               'modbus_mapping_mode': 'single',
                               'modbus_scale': '1',
                               'bacnet_enable': '1',
                               'bacnet_object_type': 'BI',
                               'bacnet_unit': '95'},
                'tamperStatus': {'name': 'tamperStatus',
                                 'json_key': 'tamperStatus',
                                 'data_type': 'bool',
                                 'unit': 'none',
                                 'readwrite': '0',
                                 'description': 'Tamper Detection Status (true=tampered)',
                                 'modbus_enable': '1',
                                 'modbus_table': 'holding',
                                 'modbus_register_count': '1',
                                 'modbus_mapping_mode': 'single',
                                 'modbus_scale': '1',
                                 'bacnet_enable': '1',
                                 'bacnet_object_type': 'BI',
                                 'bacnet_unit': '95'},
                'doorEvent': {'name': 'doorEvent',
                              'json_key': 'doorEvent',
                              'data_type': 'int',
                              'unit': 'none',
                              'readwrite': '0',
                              'min_value': '0',
                              'max_value': '255',
                              'description': 'Door Open/Close Event',
                              'modbus_enable': '1',
                              'modbus_table': 'holding',
                              'modbus_register_count': '1',
                              'modbus_mapping_mode': 'single',
                              'modbus_scale': '1',
                              'bacnet_enable': '1',
                              'bacnet_object_type': 'AI',
                              'bacnet_unit': '95'},
                'sosEvent': {'name': 'sosEvent',
                             'json_key': 'sosEvent',
                             'data_type': 'bool',
                             'unit': 'none',
                             'readwrite': '0',
                             'description': 'SOS Emergency Event',
                             'modbus_enable': '1',
                             'modbus_table': 'holding',
                             'modbus_register_count': '1',
                             'modbus_mapping_mode': 'single',
                             'modbus_scale': '1',
                             'bacnet_enable': '1',
                             'bacnet_object_type': 'BI',
                             'bacnet_unit': '95'},
                'smokeEvent': {'name': 'smokeEvent',
                               'json_key': 'smokeEvent',
                               'data_type': 'int',
                               'unit': 'none',
                               'readwrite': '0',
                               'min_value': '0',
                               'max_value': '255',
                               'description': 'Smoke alarm event code',
                               'modbus_enable': '1',
                               'modbus_table': 'holding',
                               'modbus_register_count': '1',
                               'modbus_mapping_mode': 'single',
                               'modbus_scale': '1',
                               'bacnet_enable': '1',
                               'bacnet_object_type': 'AI',
                               'bacnet_unit': '95'},
                'selfCheckEvent': {'name': 'selfCheckEvent',
                                   'json_key': 'selfCheckEvent',
                                   'data_type': 'int',
                                   'unit': 'none',
                                   'readwrite': '0',
                                   'min_value': '0',
                                   'max_value': '255',
                                   'description': 'Sensor self-check event code',
                                   'modbus_enable': '1',
                                   'modbus_table': 'holding',
                                   'modbus_register_count': '1',
                                   'modbus_mapping_mode': 'single',
                                   'modbus_scale': '1',
                                   'bacnet_enable': '1',
                                   'bacnet_object_type': 'AI',
                                   'bacnet_unit': '95'},
                'smokeStatus': {'name': 'smokeStatus',
                                'json_key': 'smokeStatus',
                                'data_type': 'int',
                                'unit': 'none',
                                'readwrite': '0',
                                'min_value': '0',
                                'max_value': '255',
                                'description': 'Smoke alarm status code',
                                'modbus_enable': '1',
                                'modbus_table': 'holding',
                                'modbus_register_count': '1',
                                'modbus_mapping_mode': 'single',
                                'modbus_scale': '1',
                                'bacnet_enable': '1',
                                'bacnet_object_type': 'AI',
                                'bacnet_unit': '95'},
                'sosEventTime': {'name': 'sosEventTime',
                                 'json_key': 'sosEventTime',
                                 'data_type': 'timestamp',
                                 'unit': 'second',
                                 'readwrite': '0',
                                 'description': 'SOS Event Timestamp (Unix timestamp)',
                                 'modbus_enable': '1',
                                 'modbus_table': 'holding',
                                 'modbus_register_count': '2',
                                 'modbus_mapping_mode': 'big_endian',
                                 'modbus_scale': '1',
                                 'bacnet_enable': '1',
                                 'bacnet_object_type': 'AI',
                                 'bacnet_unit': '73'},
                'voltageA': {'name': 'voltageA',
                             'json_key': 'voltageA',
                             'data_type': 'float',
                             'unit': 'volt',
                             'decimal_places': '1',
                             'min_value': '0',
                             'max_value': '300',
                             'readwrite': '0',
                             'description': 'A-phase voltage',
                             'modbus_enable': '1',
                             'modbus_table': 'holding',
                             'modbus_register_count': '1',
                             'modbus_mapping_mode': 'single',
                             'modbus_scale': '10',
                             'bacnet_enable': '1',
                             'bacnet_object_type': 'AI',
                             'bacnet_unit': '5'},
                'voltageB': {'name': 'voltageB',
                             'json_key': 'voltageB',
                             'data_type': 'float',
                             'unit': 'volt',
                             'decimal_places': '1',
                             'min_value': '0',
                             'max_value': '300',
                             'readwrite': '0',
                             'description': 'B-phase voltage',
                             'modbus_enable': '1',
                             'modbus_table': 'holding',
                             'modbus_register_count': '1',
                             'modbus_mapping_mode': 'single',
                             'modbus_scale': '10',
                             'bacnet_enable': '1',
                             'bacnet_object_type': 'AI',
                             'bacnet_unit': '5'},
                'voltageC': {'name': 'voltageC',
                             'json_key': 'voltageC',
                             'data_type': 'float',
                             'unit': 'volt',
                             'decimal_places': '1',
                             'min_value': '0',
                             'max_value': '300',
                             'readwrite': '0',
                             'description': 'C-phase voltage',
                             'modbus_enable': '1',
                             'modbus_table': 'holding',
                             'modbus_register_count': '1',
                             'modbus_mapping_mode': 'single',
                             'modbus_scale': '10',
                             'bacnet_enable': '1',
                             'bacnet_object_type': 'AI',
                             'bacnet_unit': '5'},
                'voltageAvg': {'name': 'voltageAvg',
                               'json_key': 'voltageAvg',
                               'data_type': 'float',
                               'unit': 'volt',
                               'decimal_places': '1',
                               'min_value': '0',
                               'max_value': '300',
                               'readwrite': '0',
                               'description': 'Average phase voltage',
                               'modbus_enable': '1',
                               'modbus_table': 'holding',
                               'modbus_register_count': '1',
                               'modbus_mapping_mode': 'single',
                               'modbus_scale': '10',
                               'bacnet_enable': '1',
                               'bacnet_object_type': 'AI',
                               'bacnet_unit': '5'},
                'currentA': {'name': 'currentA',
                             'json_key': 'currentA',
                             'data_type': 'float',
                             'unit': 'ampere',
                             'decimal_places': '1',
                             'min_value': '0',
                             'max_value': '100',
                             'readwrite': '0',
                             'description': 'A-phase current',
                             'modbus_enable': '1',
                             'modbus_table': 'holding',
                             'modbus_register_count': '1',
                             'modbus_mapping_mode': 'single',
                             'modbus_scale': '10',
                             'bacnet_enable': '1',
                             'bacnet_object_type': 'AI',
                             'bacnet_unit': '3'},
                'currentB': {'name': 'currentB',
                             'json_key': 'currentB',
                             'data_type': 'float',
                             'unit': 'ampere',
                             'decimal_places': '1',
                             'min_value': '0',
                             'max_value': '100',
                             'readwrite': '0',
                             'description': 'B-phase current',
                             'modbus_enable': '1',
                             'modbus_table': 'holding',
                             'modbus_register_count': '1',
                             'modbus_mapping_mode': 'single',
                             'modbus_scale': '10',
                             'bacnet_enable': '1',
                             'bacnet_object_type': 'AI',
                             'bacnet_unit': '3'},
                'currentC': {'name': 'currentC',
                             'json_key': 'currentC',
                             'data_type': 'float',
                             'unit': 'ampere',
                             'decimal_places': '1',
                             'min_value': '0',
                             'max_value': '100',
                             'readwrite': '0',
                             'description': 'C-phase current',
                             'modbus_enable': '1',
                             'modbus_table': 'holding',
                             'modbus_register_count': '1',
                             'modbus_mapping_mode': 'single',
                             'modbus_scale': '10',
                             'bacnet_enable': '1',
                             'bacnet_object_type': 'AI',
                             'bacnet_unit': '3'},
                'activePowerA': {'name': 'activePowerA',
                                 'json_key': 'activePowerA',
                                 'data_type': 'float',
                                 'unit': 'watt',
                                 'decimal_places': '2',
                                 'min_value': '0',
                                 'max_value': '10000',
                                 'readwrite': '0',
                                 'description': 'A-phase active power',
                                 'modbus_enable': '1',
                                 'modbus_table': 'holding',
                                 'modbus_register_count': '2',
                                 'modbus_mapping_mode': 'big_endian',
                                 'modbus_scale': '1',
                                 'bacnet_enable': '1',
                                 'bacnet_object_type': 'AI',
                                 'bacnet_unit': '47'},
                'activePowerTotal': {'name': 'activePowerTotal',
                                     'json_key': 'activePowerTotal',
                                     'data_type': 'float',
                                     'unit': 'watt',
                                     'decimal_places': '2',
                                     'min_value': '0',
                                     'max_value': '30000',
                                     'readwrite': '0',
                                     'description': 'Total active power',
                                     'modbus_enable': '1',
                                     'modbus_table': 'holding',
                                     'modbus_register_count': '2',
                                     'modbus_mapping_mode': 'big_endian',
                                     'modbus_scale': '1',
                                     'bacnet_enable': '1',
                                     'bacnet_object_type': 'AI',
                                     'bacnet_unit': '47'},
                'powerFactorTotal': {'name': 'powerFactorTotal',
                                     'json_key': 'powerFactorTotal',
                                     'data_type': 'float',
                                     'unit': 'none',
                                     'decimal_places': '3',
                                     'min_value': '-1',
                                     'max_value': '1',
                                     'readwrite': '0',
                                     'description': 'Total power factor',
                                     'modbus_enable': '1',
                                     'modbus_table': 'holding',
                                     'modbus_register_count': '2',
                                     'modbus_mapping_mode': 'big_endian',
                                     'modbus_scale': '1',
                                     'bacnet_enable': '1',
                                     'bacnet_object_type': 'AI',
                                     'bacnet_unit': '95'},
                'activeEnergy': {'name': 'activeEnergy',
                                 'json_key': 'activeEnergy',
                                 'data_type': 'float',
                                 'unit': 'kilowatt_hour',
                                 'decimal_places': '2',
                                 'min_value': '0',
                                 'max_value': '999999',
                                 'readwrite': '0',
                                 'description': 'Active energy consumption',
                                 'modbus_enable': '1',
                                 'modbus_table': 'holding',
                                 'modbus_register_count': '2',
                                 'modbus_mapping_mode': 'big_endian',
                                 'modbus_scale': '1',
                                 'bacnet_enable': '1',
                                 'bacnet_object_type': 'AI',
                                 'bacnet_unit': '19'},
                'leakageCurrent': {'name': 'leakageCurrent',
                                   'json_key': 'leakageCurrent',
                                   'data_type': 'float',
                                   'unit': 'milliampere',
                                   'decimal_places': '1',
                                   'min_value': '0',
                                   'max_value': '5000',
                                   'readwrite': '0',
                                   'description': 'Leakage current',
                                   'modbus_enable': '1',
                                   'modbus_table': 'holding',
                                   'modbus_register_count': '1',
                                   'modbus_mapping_mode': 'single',
                                   'modbus_scale': '10',
                                   'bacnet_enable': '1',
                                   'bacnet_object_type': 'AI',
                                   'bacnet_unit': '2'},
                'tempSensor1': {'name': 'tempSensor1',
                                'json_key': 'tempSensor1',
                                'data_type': 'float',
                                'unit': 'celsius',
                                'decimal_places': '1',
                                'min_value': '-20',
                                'max_value': '110',
                                'readwrite': '0',
                                'description': 'Temperature sensor 1',
                                'modbus_enable': '1',
                                'modbus_table': 'holding',
                                'modbus_register_count': '1',
                                'modbus_mapping_mode': 'single',
                                'modbus_scale': '10',
                                'bacnet_enable': '1',
                                'bacnet_object_type': 'AI',
                                'bacnet_unit': '62'},
                'tempAvg': {'name': 'tempAvg',
                            'json_key': 'tempAvg',
                            'data_type': 'float',
                            'unit': 'celsius',
                            'decimal_places': '1',
                            'min_value': '-20',
                            'max_value': '110',
                            'readwrite': '0',
                            'description': 'Average temperature',
                            'modbus_enable': '1',
                            'modbus_table': 'holding',
                            'modbus_register_count': '1',
                            'modbus_mapping_mode': 'single',
                            'modbus_scale': '10',
                            'bacnet_enable': '1',
                            'bacnet_object_type': 'AI',
                            'bacnet_unit': '62'},
                'envTemperature': {'name': 'envTemperature',
                                   'json_key': 'envTemperature',
                                   'data_type': 'float',
                                   'unit': 'celsius',
                                   'decimal_places': '1',
                                   'min_value': '-20',
                                   'max_value': '85',
                                   'readwrite': '0',
                                   'description': 'Environment temperature',
                                   'modbus_enable': '1',
                                   'modbus_table': 'holding',
                                   'modbus_register_count': '1',
                                   'modbus_mapping_mode': 'single',
                                   'modbus_scale': '10',
                                   'bacnet_enable': '1',
                                   'bacnet_object_type': 'AI',
                                   'bacnet_unit': '62'},
                'envHumidity': {'name': 'envHumidity',
                                'json_key': 'envHumidity',
                                'data_type': 'float',
                                'unit': 'percent',
                                'decimal_places': '1',
                                'min_value': '0',
                                'max_value': '100',
                                'readwrite': '0',
                                'description': 'Environment humidity',
                                'modbus_enable': '1',
                                'modbus_table': 'holding',
                                'modbus_register_count': '1',
                                'modbus_mapping_mode': 'single',
                                'modbus_scale': '10',
                                'bacnet_enable': '1',
                                'bacnet_object_type': 'AI',
                                'bacnet_unit': '98'},
                'electricalAlarm': {'name': 'electricalAlarm',
                                    'json_key': 'electricalAlarm',
                                    'data_type': 'bool',
                                    'unit': 'none',
                                    'readwrite': '0',
                                    'description': 'Electrical alarm active',
                                    'modbus_enable': '1',
                                    'modbus_table': 'holding',
                                    'modbus_register_count': '1',
                                    'modbus_mapping_mode': 'single',
                                    'modbus_scale': '1',
                                    'bacnet_enable': '1',
                                    'bacnet_object_type': 'BI',
                                    'bacnet_unit': '95'},
                'alarmOvercurrentA': {'name': 'alarmOvercurrentA',
                                      'json_key': 'alarmOvercurrentA',
                                      'data_type': 'bool',
                                      'unit': 'none',
                                      'readwrite': '0',
                                      'description': 'A-phase overcurrent alarm',
                                      'modbus_enable': '1',
                                      'modbus_table': 'holding',
                                      'modbus_register_count': '1',
                                      'modbus_mapping_mode': 'single',
                                      'modbus_scale': '1',
                                      'bacnet_enable': '1',
                                      'bacnet_object_type': 'BI',
                                      'bacnet_unit': '95'},
                'alarmLeakage': {'name': 'alarmLeakage',
                                 'json_key': 'alarmLeakage',
                                 'data_type': 'bool',
                                 'unit': 'none',
                                 'readwrite': '0',
                                 'description': 'Leakage current alarm',
                                 'modbus_enable': '1',
                                 'modbus_table': 'holding',
                                 'modbus_register_count': '1',
                                 'modbus_mapping_mode': 'single',
                                 'modbus_scale': '1',
                                 'bacnet_enable': '1',
                                 'bacnet_object_type': 'BI',
                                 'bacnet_unit': '95'},
                'tiltAngle': {'name': 'tiltAngle',
                              'json_key': 'tiltAngle',
                              'data_type': 'int',
                              'unit': 'degree',
                              'min_value': '0',
                              'max_value': '360',
                              'readwrite': '0',
                              'description': 'Tilt angle in degrees',
                              'modbus_enable': '1',
                              'modbus_table': 'holding',
                              'modbus_register_count': '1',
                              'modbus_mapping_mode': 'single',
                              'modbus_scale': '1',
                              'bacnet_enable': '1',
                              'bacnet_object_type': 'AI',
                              'bacnet_unit': '96'},
                'illuminance': {'name': 'illuminance',
                                'json_key': 'illuminance',
                                'data_type': 'int',
                                'unit': 'lux',
                                'min_value': '0',
                                'max_value': '100000',
                                'readwrite': '0',
                                'description': 'Light illuminance in Lux',
                                'modbus_enable': '1',
                                'modbus_table': 'holding',
                                'modbus_register_count': '2',
                                'modbus_mapping_mode': 'big_endian',
                                'modbus_scale': '1',
                                'bacnet_enable': '1',
                                'bacnet_object_type': 'AI',
                                'bacnet_unit': '86'},
                'liquidLevel': {'name': 'liquidLevel',
                                'json_key': 'liquidLevel',
                                'data_type': 'float',
                                'unit': 'meter',
                                'decimal_places': '2',
                                'min_value': '0',
                                'max_value': '100',
                                'readwrite': '0',
                                'description': 'Liquid level in meters',
                                'modbus_enable': '1',
                                'modbus_table': 'holding',
                                'modbus_register_count': '1',
                                'modbus_mapping_mode': 'single',
                                'modbus_scale': '100',
                                'bacnet_enable': '1',
                                'bacnet_object_type': 'AI',
                                'bacnet_unit': '31'},
                'liquidLevelPercent': {'name': 'liquidLevelPercent',
                                       'json_key': 'liquidLevelPercent',
                                       'data_type': 'float',
                                       'unit': 'percent',
                                       'decimal_places': '1',
                                       'min_value': '0',
                                       'max_value': '100',
                                       'readwrite': '0',
                                       'description': 'Liquid level percentage',
                                       'modbus_enable': '1',
                                       'modbus_table': 'holding',
                                       'modbus_register_count': '1',
                                       'modbus_mapping_mode': 'single',
                                       'modbus_scale': '10',
                                       'bacnet_enable': '1',
                                       'bacnet_object_type': 'AI',
                                       'bacnet_unit': '98'},
                'atmosphericPressure': {'name': 'atmosphericPressure',
                                        'json_key': 'atmosphericPressure',
                                        'data_type': 'int',
                                        'unit': 'pascal',
                                        'min_value': '80000',
                                        'max_value': '120000',
                                        'readwrite': '0',
                                        'description': 'Atmospheric pressure in Pascals',
                                        'modbus_enable': '1',
                                        'modbus_table': 'holding',
                                        'modbus_register_count': '2',
                                        'modbus_mapping_mode': 'big_endian',
                                        'modbus_scale': '1',
                                        'bacnet_enable': '1',
                                        'bacnet_object_type': 'AI',
                                        'bacnet_unit': '100'},
                'altitude': {'name': 'altitude',
                             'json_key': 'altitude',
                             'data_type': 'float',
                             'unit': 'meter',
                             'decimal_places': '1',
                             'min_value': '-1000',
                             'max_value': '10000',
                             'readwrite': '0',
                             'description': 'altitude',
                             'modbus_enable': '1',
                             'modbus_table': 'holding',
                             'modbus_register_count': '2',
                             'modbus_mapping_mode': 'big_endian',
                             'modbus_scale': '1',
                             'bacnet_enable': '1',
                             'bacnet_object_type': 'AI',
                             'bacnet_unit': '31'},
                'switch1State': {'name': 'switch1State',
                                 'json_key': 'switch1State',
                                 'data_type': 'bool',
                                 'unit': 'none',
                                 'readwrite': '1',
                                 'description': 'Switch 1 state (0=off, 1=on)',
                                 'modbus_enable': '1',
                                 'modbus_table': 'holding',
                                 'modbus_register_count': '1',
                                 'modbus_mapping_mode': 'single',
                                 'modbus_scale': '1',
                                 'bacnet_enable': '1',
                                 'bacnet_object_type': 'BV',
                                 'bacnet_unit': '95'},
                'switch2State': {'name': 'switch2State',
                                 'json_key': 'switch2State',
                                 'data_type': 'bool',
                                 'unit': 'none',
                                 'readwrite': '1',
                                 'description': 'Switch 2 state (0=off, 1=on)',
                                 'modbus_enable': '1',
                                 'modbus_table': 'holding',
                                 'modbus_register_count': '1',
                                 'modbus_mapping_mode': 'single',
                                 'modbus_scale': '1',
                                 'bacnet_enable': '1',
                                 'bacnet_object_type': 'BV',
                                 'bacnet_unit': '95'},
                'switch3State': {'name': 'switch3State',
                                 'json_key': 'switch3State',
                                 'data_type': 'bool',
                                 'unit': 'none',
                                 'readwrite': '1',
                                 'description': 'Switch 3 state (0=off, 1=on)',
                                 'modbus_enable': '1',
                                 'modbus_table': 'holding',
                                 'modbus_register_count': '1',
                                 'modbus_mapping_mode': 'single',
                                 'modbus_scale': '1',
                                 'bacnet_enable': '1',
                                 'bacnet_object_type': 'BV',
                                 'bacnet_unit': '95'},
                'alarmStatus': {'name': 'alarmStatus',
                                'json_key': 'alarmStatus',
                                'data_type': 'bool',
                                'unit': 'none',
                                'readwrite': '1',
                                'description': 'Sound & light alarm status (0=off, 1=on)',
                                'modbus_enable': '1',
                                'modbus_table': 'holding',
                                'modbus_register_count': '1',
                                'modbus_mapping_mode': 'single',
                                'modbus_scale': '1',
                                'bacnet_enable': '1',
                                'bacnet_object_type': 'BV',
                                'bacnet_unit': '95'},
                'alarmDurationSeconds': {'name': 'alarmDurationSeconds',
                                         'json_key': 'alarmDurationSeconds',
                                         'data_type': 'int',
                                         'unit': 'seconds',
                                         'min_value': '0',
                                         'max_value': '65535',
                                         'readwrite': '1',
                                         'description': 'Optional auto-off delay in seconds for AN-307 alarm control',
                                         'modbus_enable': '1',
                                         'modbus_table': 'holding',
                                         'modbus_register_count': '1',
                                         'modbus_mapping_mode': 'single',
                                         'modbus_scale': '1',
                                         'bacnet_enable': '1',
                                         'bacnet_object_type': 'AV',
                                         'bacnet_unit': '73'},
                'vibFreqX': {'name': 'vibFreqX',
                             'json_key': 'vibFreqX',
                             'data_type': 'int',
                             'unit': 'hertz',
                             'min_value': '0',
                             'max_value': '1000',
                             'readwrite': '0',
                             'description': 'X-axis vibration frequency in Hz',
                             'modbus_enable': '1',
                             'modbus_table': 'holding',
                             'modbus_register_count': '1',
                             'modbus_mapping_mode': 'single',
                             'modbus_scale': '1',
                             'bacnet_enable': '1',
                             'bacnet_object_type': 'AI',
                             'bacnet_unit': '72'},
                'vibAccelX': {'name': 'vibAccelX',
                              'json_key': 'vibAccelX',
                              'data_type': 'int',
                              'unit': 'millig',
                              'min_value': '0',
                              'max_value': '20000',
                              'readwrite': '0',
                              'description': 'X-axis acceleration in mg',
                              'modbus_enable': '1',
                              'modbus_table': 'holding',
                              'modbus_register_count': '1',
                              'modbus_mapping_mode': 'single',
                              'modbus_scale': '1',
                              'bacnet_enable': '1',
                              'bacnet_object_type': 'AI',
                              'bacnet_unit': '166'},
                'vibVelX': {'name': 'vibVelX',
                            'json_key': 'vibVelX',
                            'data_type': 'float',
                            'unit': 'millimeter_per_second',
                            'decimal_places': '1',
                            'min_value': '0',
                            'max_value': '1000',
                            'readwrite': '0',
                            'description': 'X-axis velocity in mm/s',
                            'modbus_enable': '1',
                            'modbus_table': 'holding',
                            'modbus_register_count': '1',
                            'modbus_mapping_mode': 'single',
                            'modbus_scale': '10',
                            'bacnet_enable': '1',
                            'bacnet_object_type': 'AI',
                            'bacnet_unit': '134'},
                'fallAlarmStatus': {'name': 'fallAlarmStatus',
                                    'json_key': 'fallAlarmStatus',
                                    'data_type': 'bool',
                                    'unit': 'none',
                                    'readwrite': '0',
                                    'description': 'Fall detection alarm status (0=no alarm, 1=alarm)',
                                    'modbus_enable': '1',
                                    'modbus_table': 'holding',
                                    'modbus_register_count': '1',
                                    'modbus_mapping_mode': 'single',
                                    'modbus_scale': '1',
                                    'bacnet_enable': '1',
                                    'bacnet_object_type': 'BI',
                                    'bacnet_unit': '95'},
                'helmetRemovalAlarmStatus': {'name': 'helmetRemovalAlarmStatus',
                                             'json_key': 'helmetRemovalAlarmStatus',
                                             'data_type': 'bool',
                                             'unit': 'none',
                                             'readwrite': '0',
                                             'description': 'Helmet removal alarm status (0=no alarm, 1=alarm)',
                                             'modbus_enable': '1',
                                             'modbus_table': 'holding',
                                             'modbus_register_count': '1',
                                             'modbus_mapping_mode': 'single',
                                             'modbus_scale': '1',
                                             'bacnet_enable': '1',
                                             'bacnet_object_type': 'BI',
                                             'bacnet_unit': '95'},
                'electricityProximityAlarmStatus': {'name': 'electricityProximityAlarmStatus',
                                                    'json_key': 'electricityProximityAlarmStatus',
                                                    'data_type': 'bool',
                                                    'unit': 'none',
                                                    'readwrite': '0',
                                                    'description': 'Proximity to electricity alarm status (0=no alarm, '
                                                                   '1=alarm)',
                                                    'modbus_enable': '1',
                                                    'modbus_table': 'holding',
                                                    'modbus_register_count': '1',
                                                    'modbus_mapping_mode': 'single',
                                                    'modbus_scale': '1',
                                                    'bacnet_enable': '1',
                                                    'bacnet_object_type': 'BI',
                                                    'bacnet_unit': '95'},
                'temperatureAlarmStatus': {'name': 'temperatureAlarmStatus',
                                           'json_key': 'temperatureAlarmStatus',
                                           'data_type': 'int',
                                           'unit': 'none',
                                           'min_value': '0',
                                           'max_value': '3',
                                           'readwrite': '0',
                                           'description': 'Temperature alarm status (0=normal, 1=too low, 2=too high, '
                                                          '3=cannot collect)',
                                           'modbus_enable': '1',
                                           'modbus_table': 'holding',
                                           'modbus_register_count': '1',
                                           'modbus_mapping_mode': 'single',
                                           'modbus_scale': '1',
                                           'bacnet_enable': '1',
                                           'bacnet_object_type': 'AI',
                                           'bacnet_unit': '95'},
                'batteryLowAlarm': {'name': 'batteryLowAlarm',
                                    'json_key': 'batteryLowAlarm',
                                    'data_type': 'bool',
                                    'unit': 'none',
                                    'readwrite': '0',
                                    'description': 'Battery low percentage alarm',
                                    'modbus_enable': '1',
                                    'modbus_table': 'holding',
                                    'modbus_register_count': '1',
                                    'modbus_mapping_mode': 'single',
                                    'modbus_scale': '1',
                                    'bacnet_enable': '1',
                                    'bacnet_object_type': 'BI',
                                    'bacnet_unit': '95'},
                'accelerationAlarm': {'name': 'accelerationAlarm',
                                      'json_key': 'accelerationAlarm',
                                      'data_type': 'bool',
                                      'unit': 'none',
                                      'readwrite': '0',
                                      'description': 'Acceleration alarm (0=normal, 1=alarm)',
                                      'modbus_enable': '1',
                                      'modbus_table': 'holding',
                                      'modbus_register_count': '1',
                                      'modbus_mapping_mode': 'single',
                                      'modbus_scale': '1',
                                      'bacnet_enable': '1',
                                      'bacnet_object_type': 'BI',
                                      'bacnet_unit': '95'},
                'tiltAlarm': {'name': 'tiltAlarm',
                              'json_key': 'tiltAlarm',
                              'data_type': 'bool',
                              'unit': 'none',
                              'readwrite': '0',
                              'description': 'Tilt angle alarm (0=normal, 1=alarm)',
                              'modbus_enable': '1',
                              'modbus_table': 'holding',
                              'modbus_register_count': '1',
                              'modbus_mapping_mode': 'single',
                              'modbus_scale': '1',
                              'bacnet_enable': '1',
                              'bacnet_object_type': 'BI',
                              'bacnet_unit': '95'},
                'sensorAbnormal': {'name': 'sensorAbnormal',
                                   'json_key': 'sensorAbnormal',
                                   'data_type': 'bool',
                                   'unit': 'none',
                                   'readwrite': '0',
                                   'description': 'Sensor abnormal status (0=normal, 1=abnormal)',
                                   'modbus_enable': '1',
                                   'modbus_table': 'holding',
                                   'modbus_register_count': '1',
                                   'modbus_mapping_mode': 'single',
                                   'modbus_scale': '1',
                                   'bacnet_enable': '1',
                                   'bacnet_object_type': 'BI',
                                   'bacnet_unit': '95'},
                'liquidLevelStatus': {'name': 'liquidLevelStatus',
                                      'json_key': 'liquidLevelStatus',
                                      'data_type': 'int',
                                      'unit': 'none',
                                      'min_value': '0',
                                      'max_value': '2',
                                      'readwrite': '0',
                                      'description': 'Liquid level status (0=normal, 1=too low, 2=too high)',
                                      'modbus_enable': '1',
                                      'modbus_table': 'holding',
                                      'modbus_register_count': '1',
                                      'modbus_mapping_mode': 'single',
                                      'modbus_scale': '1',
                                      'bacnet_enable': '1',
                                      'bacnet_object_type': 'AI',
                                      'bacnet_unit': '95'},
                'vibrationAlarmStatus': {'name': 'vibrationAlarmStatus',
                                         'json_key': 'vibrationAlarmStatus',
                                         'data_type': 'int',
                                         'unit': 'none',
                                         'min_value': '0',
                                         'max_value': '65535',
                                         'readwrite': '0',
                                         'description': 'Vibration alarm status bitfield',
                                         'modbus_enable': '1',
                                         'modbus_table': 'holding',
                                         'modbus_register_count': '1',
                                         'modbus_mapping_mode': 'single',
                                         'modbus_scale': '1',
                                         'bacnet_enable': '1',
                                         'bacnet_object_type': 'AI',
                                         'bacnet_unit': '95'},
                'safetyAlarmActive': {'name': 'safetyAlarmActive',
                                      'json_key': 'safetyAlarmActive',
                                      'data_type': 'bool',
                                      'unit': 'none',
                                      'readwrite': '0',
                                      'description': 'Any safety alarm active (0=normal, 1=alarm)',
                                      'modbus_enable': '1',
                                      'modbus_table': 'holding',
                                      'modbus_register_count': '1',
                                      'modbus_mapping_mode': 'single',
                                      'modbus_scale': '1',
                                      'bacnet_enable': '1',
                                      'bacnet_object_type': 'BI',
                                      'bacnet_unit': '95'},
                'latitude': {'name': 'latitude',
                             'json_key': 'latitude',
                             'data_type': 'float',
                             'unit': 'degrees',
                             'decimal_places': '6',
                             'min_value': '-90',
                             'max_value': '90',
                             'readwrite': '0',
                             'description': 'GPS latitude',
                             'modbus_enable': '1',
                             'modbus_table': 'holding',
                             'modbus_register_count': '2',
                             'modbus_mapping_mode': 'big_endian',
                             'modbus_scale': '1',
                             'bacnet_enable': '1',
                             'bacnet_object_type': 'AI',
                             'bacnet_unit': '95'},
                'longitude': {'name': 'longitude',
                              'json_key': 'longitude',
                              'data_type': 'float',
                              'unit': 'degrees',
                              'decimal_places': '6',
                              'min_value': '-180',
                              'max_value': '180',
                              'readwrite': '0',
                              'description': 'GPS longitude',
                              'modbus_enable': '1',
                              'modbus_table': 'holding',
                              'modbus_register_count': '2',
                              'modbus_mapping_mode': 'big_endian',
                              'modbus_scale': '1',
                              'bacnet_enable': '1',
                              'bacnet_object_type': 'AI',
                              'bacnet_unit': '95'},
                'positionAccuracy': {'name': 'positionAccuracy',
                                     'json_key': 'positionAccuracy',
                                     'data_type': 'float',
                                     'unit': 'meter',
                                     'decimal_places': '2',
                                     'min_value': '0',
                                     'max_value': '1000',
                                     'readwrite': '0',
                                     'description': 'GPS position accuracy',
                                     'modbus_enable': '1',
                                     'modbus_table': 'holding',
                                     'modbus_register_count': '2',
                                     'modbus_mapping_mode': 'big_endian',
                                     'modbus_scale': '1',
                                     'bacnet_enable': '1',
                                     'bacnet_object_type': 'AI',
                                     'bacnet_unit': '31'},
                'gpsAbsoluteTimestamp': {'name': 'gpsAbsoluteTimestamp',
                                         'json_key': 'gpsAbsoluteTimestamp',
                                         'data_type': 'timestamp',
                                         'unit': 'second',
                                         'readwrite': '0',
                                         'description': 'GPS absolute timestamp',
                                         'modbus_enable': '1',
                                         'modbus_table': 'holding',
                                         'modbus_register_count': '2',
                                         'modbus_mapping_mode': 'big_endian',
                                         'modbus_scale': '1',
                                         'bacnet_enable': '1',
                                         'bacnet_object_type': 'AI',
                                         'bacnet_unit': '73'},
                'gpsTimeValid': {'name': 'gpsTimeValid',
                                 'json_key': 'gpsTimeValid',
                                 'data_type': 'bool',
                                 'unit': 'none',
                                 'readwrite': '0',
                                 'description': 'time-valid flag',
                                 'modbus_enable': '1',
                                 'modbus_table': 'holding',
                                 'modbus_register_count': '1',
                                 'modbus_mapping_mode': 'single',
                                 'modbus_scale': '1',
                                 'bacnet_enable': '1',
                                 'bacnet_object_type': 'BI',
                                 'bacnet_unit': '95'},
                'timestamp': {'name': 'timestamp',
                              'json_key': 'timestamp',
                              'data_type': 'int',
                              'unit': 'seconds',
                              'min_value': '0',
                              'max_value': '4294967295',
                              'readwrite': '0',
                              'description': 'Unix timestamp in seconds',
                              'modbus_enable': '1',
                              'modbus_table': 'holding',
                              'modbus_register_count': '2',
                              'modbus_mapping_mode': 'single',
                              'modbus_scale': '1',
                              'bacnet_enable': '1',
                              'bacnet_object_type': 'AI',
                              'bacnet_unit': '95'},
                'vibratingWireSensorModel': {'name': 'vibratingWireSensorModel',
                                             'json_key': 'vibratingWireSensorModel',
                                             'data_type': 'int',
                                             'unit': 'none',
                                             'min_value': '0',
                                             'max_value': '255',
                                             'readwrite': '0',
                                             'description': 'Vibrating wire sensor model code',
                                             'modbus_enable': '1',
                                             'modbus_table': 'holding',
                                             'modbus_register_count': '1',
                                             'modbus_mapping_mode': 'single',
                                             'modbus_scale': '1',
                                             'bacnet_enable': '1',
                                             'bacnet_object_type': 'AI',
                                             'bacnet_unit': '95'},
                'frequency': {'name': 'frequency',
                              'json_key': 'frequency',
                              'data_type': 'float',
                              'unit': 'hertz',
                              'decimal_places': '2',
                              'min_value': '0',
                              'max_value': '10000',
                              'readwrite': '0',
                              'description': 'Latest vibrating wire frequency in Hz',
                              'modbus_enable': '1',
                              'modbus_table': 'holding',
                              'modbus_register_count': '2',
                              'modbus_mapping_mode': 'big_endian',
                              'modbus_scale': '100',
                              'bacnet_enable': '1',
                              'bacnet_object_type': 'AI',
                              'bacnet_unit': '72'},
                'frequencyDigit': {'name': 'frequencyDigit',
                                   'json_key': 'frequencyDigit',
                                   'data_type': 'float',
                                   'unit': 'digit',
                                   'decimal_places': '2',
                                   'min_value': '0',
                                   'max_value': '1000000',
                                   'readwrite': '0',
                                   'description': 'Latest frequency modulus digit calculated by f^2/1000',
                                   'modbus_enable': '1',
                                   'modbus_table': 'holding',
                                   'modbus_register_count': '2',
                                   'modbus_mapping_mode': 'big_endian',
                                   'modbus_scale': '100',
                                   'bacnet_enable': '1',
                                   'bacnet_object_type': 'AI',
                                   'bacnet_unit': '95'},
                'initialFrequency': {'name': 'initialFrequency',
                                     'json_key': 'initialFrequency',
                                     'data_type': 'float',
                                     'unit': 'hertz',
                                     'decimal_places': '2',
                                     'min_value': '0',
                                     'max_value': '10000',
                                     'readwrite': '0',
                                     'description': 'Initial baseline vibrating wire frequency in Hz',
                                     'modbus_enable': '1',
                                     'modbus_table': 'holding',
                                     'modbus_register_count': '2',
                                     'modbus_mapping_mode': 'big_endian',
                                     'modbus_scale': '100',
                                     'bacnet_enable': '1',
                                     'bacnet_object_type': 'AI',
                                     'bacnet_unit': '72'},
                'initialFrequencyDigit': {'name': 'initialFrequencyDigit',
                                          'json_key': 'initialFrequencyDigit',
                                          'data_type': 'float',
                                          'unit': 'digit',
                                          'decimal_places': '2',
                                          'min_value': '0',
                                          'max_value': '1000000',
                                          'readwrite': '0',
                                          'description': 'Initial baseline frequency modulus digit calculated by '
                                                         'f^2/1000',
                                          'modbus_enable': '1',
                                          'modbus_table': 'holding',
                                          'modbus_register_count': '2',
                                          'modbus_mapping_mode': 'big_endian',
                                          'modbus_scale': '100',
                                          'bacnet_enable': '1',
                                          'bacnet_object_type': 'AI',
                                          'bacnet_unit': '95'},
                'initialTemperature': {'name': 'initialTemperature',
                                       'json_key': 'initialTemperature',
                                       'data_type': 'float',
                                       'unit': 'celsius',
                                       'decimal_places': '1',
                                       'min_value': '-100',
                                       'max_value': '500',
                                       'readwrite': '0',
                                       'description': 'Initial baseline temperature',
                                       'modbus_enable': '1',
                                       'modbus_table': 'holding',
                                       'modbus_register_count': '1',
                                       'modbus_mapping_mode': 'single',
                                       'modbus_scale': '10',
                                       'bacnet_enable': '1',
                                       'bacnet_object_type': 'AI',
                                       'bacnet_unit': '62'},
                'correctionFactor': {'name': 'correctionFactor',
                                     'json_key': 'correctionFactor',
                                     'data_type': 'float',
                                     'unit': 'none',
                                     'decimal_places': '4',
                                     'min_value': '0',
                                     'max_value': '10',
                                     'readwrite': '0',
                                     'description': 'Average correction factor C used in strain calculation, default '
                                                    '1.0',
                                     'modbus_enable': '1',
                                     'modbus_table': 'holding',
                                     'modbus_register_count': '2',
                                     'modbus_mapping_mode': 'big_endian',
                                     'modbus_scale': '10000',
                                     'bacnet_enable': '1',
                                     'bacnet_object_type': 'AI',
                                     'bacnet_unit': '95'},
                'steelStructureStrain': {'name': 'steelStructureStrain',
                                         'json_key': 'steelStructureStrain',
                                         'data_type': 'float',
                                         'unit': 'microstrain',
                                         'decimal_places': '2',
                                         'min_value': '-5000000',
                                         'max_value': '5000000',
                                         'readwrite': '0',
                                         'description': 'Calculated strain for surface-mounted steel structure in '
                                                        'microstrain',
                                         'modbus_enable': '1',
                                         'modbus_table': 'holding',
                                         'modbus_register_count': '2',
                                         'modbus_mapping_mode': 'big_endian',
                                         'modbus_scale': '100',
                                         'bacnet_enable': '1',
                                         'bacnet_object_type': 'AI',
                                         'bacnet_unit': '95'},
                'concreteStructureStrain': {'name': 'concreteStructureStrain',
                                            'json_key': 'concreteStructureStrain',
                                            'data_type': 'float',
                                            'unit': 'microstrain',
                                            'decimal_places': '2',
                                            'min_value': '-5000000',
                                            'max_value': '5000000',
                                            'readwrite': '0',
                                            'description': 'Calculated strain for surface-mounted concrete structure '
                                                           'in microstrain',
                                            'modbus_enable': '1',
                                            'modbus_table': 'holding',
                                            'modbus_register_count': '2',
                                            'modbus_mapping_mode': 'big_endian',
                                            'modbus_scale': '100',
                                            'bacnet_enable': '1',
                                            'bacnet_object_type': 'AI',
                                            'bacnet_unit': '95'},
                'isHeartbeat': {'name': 'isHeartbeat',
                                'json_key': 'isHeartbeat',
                                'data_type': 'bool',
                                'unit': 'none',
                                'readwrite': '0',
                                'description': 'Heartbeat message indicator',
                                'modbus_enable': '1',
                                'modbus_table': 'holding',
                                'modbus_register_count': '1',
                                'modbus_mapping_mode': 'single',
                                'modbus_scale': '1',
                                'bacnet_enable': '1',
                                'bacnet_object_type': 'BI',
                                'bacnet_unit': '95'},
                'beaconIdHex': {'name': 'beaconIdHex',
                                'json_key': 'beaconIdHex',
                                'data_type': 'string',
                                'unit': 'none',
                                'string_max_len': '32',
                                'readwrite': '0',
                                'description': 'Latest beacon identifier in hexadecimal',
                                'modbus_enable': '1',
                                'modbus_table': 'holding',
                                'modbus_register_count': '16',
                                'modbus_mapping_mode': 'string',
                                'bacnet_enable': '1',
                                'bacnet_object_type': 'CV',
                                'bacnet_unit': '95'},
                'beaconRssi': {'name': 'beaconRssi',
                               'json_key': 'beaconRssi',
                               'data_type': 'int',
                               'unit': 'none',
                               'min_value': '-120',
                               'max_value': '0',
                               'readwrite': '0',
                               'description': 'Latest beacon RSSI signal strength',
                               'modbus_enable': '1',
                               'modbus_table': 'holding',
                               'modbus_register_count': '1',
                               'modbus_mapping_mode': 'single',
                               'modbus_scale': '1',
                               'bacnet_enable': '1',
                               'bacnet_object_type': 'AI',
                               'bacnet_unit': '95'},
                'beaconBatteryLevel': {'name': 'beaconBatteryLevel',
                                       'json_key': 'beaconBatteryLevel',
                                       'data_type': 'int',
                                       'unit': 'percent',
                                       'min_value': '0',
                                       'max_value': '100',
                                       'readwrite': '0',
                                       'description': 'Latest beacon battery level percentage',
                                       'modbus_enable': '1',
                                       'modbus_table': 'holding',
                                       'modbus_register_count': '1',
                                       'modbus_mapping_mode': 'single',
                                       'modbus_scale': '1',
                                       'bacnet_enable': '1',
                                       'bacnet_object_type': 'AI',
                                       'bacnet_unit': '98'},
                'beaconBatteryValid': {'name': 'beaconBatteryValid',
                                       'json_key': 'beaconBatteryValid',
                                       'data_type': 'bool',
                                       'unit': 'none',
                                       'readwrite': '0',
                                       'description': 'Latest beacon battery level valid flag',
                                       'modbus_enable': '1',
                                       'modbus_table': 'holding',
                                       'modbus_register_count': '1',
                                       'modbus_mapping_mode': 'single',
                                       'modbus_scale': '1',
                                       'bacnet_enable': '1',
                                       'bacnet_object_type': 'BI',
                                       'bacnet_unit': '95'},
                'vibFreqY': {'name': 'vibFreqY',
                             'json_key': 'vibFreqY',
                             'data_type': 'int',
                             'unit': 'hertz',
                             'min_value': '0',
                             'max_value': '1000',
                             'readwrite': '0',
                             'description': 'Y-axis vibration frequency in Hz',
                             'modbus_enable': '1',
                             'modbus_table': 'holding',
                             'modbus_register_count': '1',
                             'modbus_mapping_mode': 'single',
                             'modbus_scale': '1',
                             'bacnet_enable': '1',
                             'bacnet_object_type': 'AI',
                             'bacnet_unit': '72'},
                'vibFreqZ': {'name': 'vibFreqZ',
                             'json_key': 'vibFreqZ',
                             'data_type': 'int',
                             'unit': 'hertz',
                             'min_value': '0',
                             'max_value': '1000',
                             'readwrite': '0',
                             'description': 'Z-axis vibration frequency in Hz',
                             'modbus_enable': '1',
                             'modbus_table': 'holding',
                             'modbus_register_count': '1',
                             'modbus_mapping_mode': 'single',
                             'modbus_scale': '1',
                             'bacnet_enable': '1',
                             'bacnet_object_type': 'AI',
                             'bacnet_unit': '72'},
                'vibAccelY': {'name': 'vibAccelY',
                              'json_key': 'vibAccelY',
                              'data_type': 'float',
                              'unit': 'g',
                              'decimal_places': '3',
                              'min_value': '0',
                              'max_value': '100',
                              'readwrite': '0',
                              'description': 'Y-axis vibration acceleration in g',
                              'modbus_enable': '1',
                              'modbus_table': 'holding',
                              'modbus_register_count': '1',
                              'modbus_mapping_mode': 'single',
                              'modbus_scale': '1000',
                              'bacnet_enable': '1',
                              'bacnet_object_type': 'AI',
                              'bacnet_unit': '95'},
                'vibAccelZ': {'name': 'vibAccelZ',
                              'json_key': 'vibAccelZ',
                              'data_type': 'float',
                              'unit': 'g',
                              'decimal_places': '3',
                              'min_value': '0',
                              'max_value': '100',
                              'readwrite': '0',
                              'description': 'Z-axis vibration acceleration in g',
                              'modbus_enable': '1',
                              'modbus_table': 'holding',
                              'modbus_register_count': '1',
                              'modbus_mapping_mode': 'single',
                              'modbus_scale': '1000',
                              'bacnet_enable': '1',
                              'bacnet_object_type': 'AI',
                              'bacnet_unit': '95'},
                'vibVelY': {'name': 'vibVelY',
                            'json_key': 'vibVelY',
                            'data_type': 'float',
                            'unit': 'mm/s',
                            'decimal_places': '2',
                            'min_value': '0',
                            'max_value': '1000',
                            'readwrite': '0',
                            'description': 'Y-axis vibration velocity in mm/s',
                            'modbus_enable': '1',
                            'modbus_table': 'holding',
                            'modbus_register_count': '1',
                            'modbus_mapping_mode': 'single',
                            'modbus_scale': '100',
                            'bacnet_enable': '1',
                            'bacnet_object_type': 'AI',
                            'bacnet_unit': '95'},
                'vibVelZ': {'name': 'vibVelZ',
                            'json_key': 'vibVelZ',
                            'data_type': 'float',
                            'unit': 'mm/s',
                            'decimal_places': '2',
                            'min_value': '0',
                            'max_value': '1000',
                            'readwrite': '0',
                            'description': 'Z-axis vibration velocity in mm/s',
                            'modbus_enable': '1',
                            'modbus_table': 'holding',
                            'modbus_register_count': '1',
                            'modbus_mapping_mode': 'single',
                            'modbus_scale': '100',
                            'bacnet_enable': '1',
                            'bacnet_object_type': 'AI',
                            'bacnet_unit': '95'},
                'vibDispX': {'name': 'vibDispX',
                             'json_key': 'vibDispX',
                             'data_type': 'float',
                             'unit': 'mm',
                             'decimal_places': '3',
                             'min_value': '0',
                             'max_value': '100',
                             'readwrite': '0',
                             'description': 'X-axis vibration displacement in mm',
                             'modbus_enable': '1',
                             'modbus_table': 'holding',
                             'modbus_register_count': '1',
                             'modbus_mapping_mode': 'single',
                             'modbus_scale': '1000',
                             'bacnet_enable': '1',
                             'bacnet_object_type': 'AI',
                             'bacnet_unit': '95'},
                'vibDispY': {'name': 'vibDispY',
                             'json_key': 'vibDispY',
                             'data_type': 'float',
                             'unit': 'mm',
                             'decimal_places': '3',
                             'min_value': '0',
                             'max_value': '100',
                             'readwrite': '0',
                             'description': 'Y-axis vibration displacement in mm',
                             'modbus_enable': '1',
                             'modbus_table': 'holding',
                             'modbus_register_count': '1',
                             'modbus_mapping_mode': 'single',
                             'modbus_scale': '1000',
                             'bacnet_enable': '1',
                             'bacnet_object_type': 'AI',
                             'bacnet_unit': '95'},
                'vibDispZ': {'name': 'vibDispZ',
                             'json_key': 'vibDispZ',
                             'data_type': 'float',
                             'unit': 'mm',
                             'decimal_places': '3',
                             'min_value': '0',
                             'max_value': '100',
                             'readwrite': '0',
                             'description': 'Z-axis vibration displacement in mm',
                             'modbus_enable': '1',
                             'modbus_table': 'holding',
                             'modbus_register_count': '1',
                             'modbus_mapping_mode': 'single',
                             'modbus_scale': '1000',
                             'bacnet_enable': '1',
                             'bacnet_object_type': 'AI',
                             'bacnet_unit': '95'},
                'alarmAccelX': {'name': 'alarmAccelX',
                                'json_key': 'alarmAccelX',
                                'data_type': 'float',
                                'unit': 'g',
                                'decimal_places': '3',
                                'min_value': '0',
                                'max_value': '100',
                                'readwrite': '1',
                                'description': 'X-axis acceleration alarm threshold in g',
                                'modbus_enable': '1',
                                'modbus_table': 'holding',
                                'modbus_register_count': '1',
                                'modbus_mapping_mode': 'single',
                                'modbus_scale': '1000',
                                'bacnet_enable': '1',
                                'bacnet_object_type': 'AV',
                                'bacnet_unit': '95'},
                'alarmAccelY': {'name': 'alarmAccelY',
                                'json_key': 'alarmAccelY',
                                'data_type': 'float',
                                'unit': 'g',
                                'decimal_places': '3',
                                'min_value': '0',
                                'max_value': '100',
                                'readwrite': '1',
                                'description': 'Y-axis acceleration alarm threshold in g',
                                'modbus_enable': '1',
                                'modbus_table': 'holding',
                                'modbus_register_count': '1',
                                'modbus_mapping_mode': 'single',
                                'modbus_scale': '1000',
                                'bacnet_enable': '1',
                                'bacnet_object_type': 'AV',
                                'bacnet_unit': '95'},
                'alarmAccelZ': {'name': 'alarmAccelZ',
                                'json_key': 'alarmAccelZ',
                                'data_type': 'float',
                                'unit': 'g',
                                'decimal_places': '3',
                                'min_value': '0',
                                'max_value': '100',
                                'readwrite': '1',
                                'description': 'Z-axis acceleration alarm threshold in g',
                                'modbus_enable': '1',
                                'modbus_table': 'holding',
                                'modbus_register_count': '1',
                                'modbus_mapping_mode': 'single',
                                'modbus_scale': '1000',
                                'bacnet_enable': '1',
                                'bacnet_object_type': 'AV',
                                'bacnet_unit': '95'},
                'alarmVelX': {'name': 'alarmVelX',
                              'json_key': 'alarmVelX',
                              'data_type': 'float',
                              'unit': 'mm/s',
                              'decimal_places': '2',
                              'min_value': '0',
                              'max_value': '1000',
                              'readwrite': '1',
                              'description': 'X-axis velocity alarm threshold in mm/s',
                              'modbus_enable': '1',
                              'modbus_table': 'holding',
                              'modbus_register_count': '1',
                              'modbus_mapping_mode': 'single',
                              'modbus_scale': '100',
                              'bacnet_enable': '1',
                              'bacnet_object_type': 'AV',
                              'bacnet_unit': '95'},
                'alarmVelY': {'name': 'alarmVelY',
                              'json_key': 'alarmVelY',
                              'data_type': 'float',
                              'unit': 'mm/s',
                              'decimal_places': '2',
                              'min_value': '0',
                              'max_value': '1000',
                              'readwrite': '1',
                              'description': 'Y-axis velocity alarm threshold in mm/s',
                              'modbus_enable': '1',
                              'modbus_table': 'holding',
                              'modbus_register_count': '1',
                              'modbus_mapping_mode': 'single',
                              'modbus_scale': '100',
                              'bacnet_enable': '1',
                              'bacnet_object_type': 'AV',
                              'bacnet_unit': '95'},
                'alarmVelZ': {'name': 'alarmVelZ',
                              'json_key': 'alarmVelZ',
                              'data_type': 'float',
                              'unit': 'mm/s',
                              'decimal_places': '2',
                              'min_value': '0',
                              'max_value': '1000',
                              'readwrite': '1',
                              'description': 'Z-axis velocity alarm threshold in mm/s',
                              'modbus_enable': '1',
                              'modbus_table': 'holding',
                              'modbus_register_count': '1',
                              'modbus_mapping_mode': 'single',
                              'modbus_scale': '100',
                              'bacnet_enable': '1',
                              'bacnet_object_type': 'AV',
                              'bacnet_unit': '95'},
                'alarmDispX': {'name': 'alarmDispX',
                               'json_key': 'alarmDispX',
                               'data_type': 'float',
                               'unit': 'mm',
                               'decimal_places': '3',
                               'min_value': '0',
                               'max_value': '100',
                               'readwrite': '1',
                               'description': 'X-axis displacement alarm threshold in mm',
                               'modbus_enable': '1',
                               'modbus_table': 'holding',
                               'modbus_register_count': '1',
                               'modbus_mapping_mode': 'single',
                               'modbus_scale': '1000',
                               'bacnet_enable': '1',
                               'bacnet_object_type': 'AV',
                               'bacnet_unit': '95'},
                'alarmDispY': {'name': 'alarmDispY',
                               'json_key': 'alarmDispY',
                               'data_type': 'float',
                               'unit': 'mm',
                               'decimal_places': '3',
                               'min_value': '0',
                               'max_value': '100',
                               'readwrite': '1',
                               'description': 'Y-axis displacement alarm threshold in mm',
                               'modbus_enable': '1',
                               'modbus_table': 'holding',
                               'modbus_register_count': '1',
                               'modbus_mapping_mode': 'single',
                               'modbus_scale': '1000',
                               'bacnet_enable': '1',
                               'bacnet_object_type': 'AV',
                               'bacnet_unit': '95'},
                'alarmDispZ': {'name': 'alarmDispZ',
                               'json_key': 'alarmDispZ',
                               'data_type': 'float',
                               'unit': 'mm',
                               'decimal_places': '3',
                               'min_value': '0',
                               'max_value': '100',
                               'readwrite': '1',
                               'description': 'Z-axis displacement alarm threshold in mm',
                               'modbus_enable': '1',
                               'modbus_table': 'holding',
                               'modbus_register_count': '1',
                               'modbus_mapping_mode': 'single',
                               'modbus_scale': '1000',
                               'bacnet_enable': '1',
                               'bacnet_object_type': 'AV',
                               'bacnet_unit': '95'},
                'timerOpenEnabled1': {'name': 'timerOpenEnabled1',
                                      'json_key': 'timerOpenEnabled1',
                                      'data_type': 'bool',
                                      'unit': 'none',
                                      'readwrite': '0',
                                      'description': 'Timer open enable for channel 1',
                                      'modbus_enable': '1',
                                      'modbus_table': 'holding',
                                      'modbus_register_count': '1',
                                      'modbus_mapping_mode': 'single',
                                      'modbus_scale': '1',
                                      'bacnet_enable': '1',
                                      'bacnet_object_type': 'BV',
                                      'bacnet_unit': '95'},
                'timerOpenEnabled2': {'name': 'timerOpenEnabled2',
                                      'json_key': 'timerOpenEnabled2',
                                      'data_type': 'bool',
                                      'unit': 'none',
                                      'readwrite': '0',
                                      'description': 'Timer open enable for channel 2',
                                      'modbus_enable': '1',
                                      'modbus_table': 'holding',
                                      'modbus_register_count': '1',
                                      'modbus_mapping_mode': 'single',
                                      'modbus_scale': '1',
                                      'bacnet_enable': '1',
                                      'bacnet_object_type': 'BV',
                                      'bacnet_unit': '95'},
                'timerOpenEnabled3': {'name': 'timerOpenEnabled3',
                                      'json_key': 'timerOpenEnabled3',
                                      'data_type': 'bool',
                                      'unit': 'none',
                                      'readwrite': '0',
                                      'description': 'Timer open enable for channel 3',
                                      'modbus_enable': '1',
                                      'modbus_table': 'holding',
                                      'modbus_register_count': '1',
                                      'modbus_mapping_mode': 'single',
                                      'modbus_scale': '1',
                                      'bacnet_enable': '1',
                                      'bacnet_object_type': 'BV',
                                      'bacnet_unit': '95'},
                'timerCloseEnabled1': {'name': 'timerCloseEnabled1',
                                       'json_key': 'timerCloseEnabled1',
                                       'data_type': 'bool',
                                       'unit': 'none',
                                       'readwrite': '0',
                                       'description': 'Timer close enable for channel 1',
                                       'modbus_enable': '1',
                                       'modbus_table': 'holding',
                                       'modbus_register_count': '1',
                                       'modbus_mapping_mode': 'single',
                                       'modbus_scale': '1',
                                       'bacnet_enable': '1',
                                       'bacnet_object_type': 'BV',
                                       'bacnet_unit': '95'},
                'timerCloseEnabled2': {'name': 'timerCloseEnabled2',
                                       'json_key': 'timerCloseEnabled2',
                                       'data_type': 'bool',
                                       'unit': 'none',
                                       'readwrite': '0',
                                       'description': 'Timer close enable for channel 2',
                                       'modbus_enable': '1',
                                       'modbus_table': 'holding',
                                       'modbus_register_count': '1',
                                       'modbus_mapping_mode': 'single',
                                       'modbus_scale': '1',
                                       'bacnet_enable': '1',
                                       'bacnet_object_type': 'BV',
                                       'bacnet_unit': '95'},
                'timerCloseEnabled3': {'name': 'timerCloseEnabled3',
                                       'json_key': 'timerCloseEnabled3',
                                       'data_type': 'bool',
                                       'unit': 'none',
                                       'readwrite': '0',
                                       'description': 'Timer close enable for channel 3',
                                       'modbus_enable': '1',
                                       'modbus_table': 'holding',
                                       'modbus_register_count': '1',
                                       'modbus_mapping_mode': 'single',
                                       'modbus_scale': '1',
                                       'bacnet_enable': '1',
                                       'bacnet_object_type': 'BV',
                                       'bacnet_unit': '95'},
                'temperatureEvent': {'name': 'temperatureEvent',
                                     'json_key': 'temperatureEvent',
                                     'data_type': 'bool',
                                     'unit': 'none',
                                     'readwrite': '0',
                                     'description': 'Temperature alarm event',
                                     'modbus_enable': '1',
                                     'modbus_table': 'holding',
                                     'modbus_register_count': '1',
                                     'modbus_mapping_mode': 'single',
                                     'modbus_scale': '1',
                                     'bacnet_enable': '1',
                                     'bacnet_object_type': 'BI',
                                     'bacnet_unit': '95'},
                'presenceEvent': {'name': 'presenceEvent',
                                  'json_key': 'presenceEvent',
                                  'data_type': 'int',
                                  'unit': 'none',
                                  'readwrite': '0',
                                  'min_value': '0',
                                  'max_value': '255',
                                  'description': 'Presence detection event code',
                                  'modbus_enable': '1',
                                  'modbus_table': 'holding',
                                  'modbus_register_count': '1',
                                  'modbus_mapping_mode': 'single',
                                  'modbus_scale': '1',
                                  'bacnet_enable': '1',
                                  'bacnet_object_type': 'AI',
                                  'bacnet_unit': '95'},
                'liquidLevelEvent': {'name': 'liquidLevelEvent',
                                     'json_key': 'liquidLevelEvent',
                                     'data_type': 'int',
                                     'unit': 'none',
                                     'readwrite': '0',
                                     'min_value': '0',
                                     'max_value': '255',
                                     'description': 'Liquid level change event code',
                                     'modbus_enable': '1',
                                     'modbus_table': 'holding',
                                     'modbus_register_count': '1',
                                     'modbus_mapping_mode': 'single',
                                     'modbus_scale': '1',
                                     'bacnet_enable': '1',
                                     'bacnet_object_type': 'AI',
                                     'bacnet_unit': '95'},
                'vibrationAlarmEvent': {'name': 'vibrationAlarmEvent',
                                        'json_key': 'vibrationAlarmEvent',
                                        'data_type': 'bool',
                                        'unit': 'none',
                                        'readwrite': '0',
                                        'description': 'Vibration alarm event',
                                        'modbus_enable': '1',
                                        'modbus_table': 'holding',
                                        'modbus_register_count': '1',
                                        'modbus_mapping_mode': 'single',
                                        'modbus_scale': '1',
                                        'bacnet_enable': '1',
                                        'bacnet_object_type': 'BI',
                                        'bacnet_unit': '95'},
                'fallAlarmEvent': {'name': 'fallAlarmEvent',
                                   'json_key': 'fallAlarmEvent',
                                   'data_type': 'bool',
                                   'unit': 'none',
                                   'readwrite': '0',
                                   'description': 'Fall detection alarm event',
                                   'modbus_enable': '1',
                                   'modbus_table': 'holding',
                                   'modbus_register_count': '1',
                                   'modbus_mapping_mode': 'single',
                                   'modbus_scale': '1',
                                   'bacnet_enable': '1',
                                   'bacnet_object_type': 'BI',
                                   'bacnet_unit': '95'},
                'helmetRemovalAlarmEvent': {'name': 'helmetRemovalAlarmEvent',
                                            'json_key': 'helmetRemovalAlarmEvent',
                                            'data_type': 'bool',
                                            'unit': 'none',
                                            'readwrite': '0',
                                            'description': 'Helmet removal alarm event',
                                            'modbus_enable': '1',
                                            'modbus_table': 'holding',
                                            'modbus_register_count': '1',
                                            'modbus_mapping_mode': 'single',
                                            'modbus_scale': '1',
                                            'bacnet_enable': '1',
                                            'bacnet_object_type': 'BI',
                                            'bacnet_unit': '95'},
                'electricityProximityAlarmEvent': {'name': 'electricityProximityAlarmEvent',
                                                   'json_key': 'electricityProximityAlarmEvent',
                                                   'data_type': 'bool',
                                                   'unit': 'none',
                                                   'readwrite': '0',
                                                   'description': 'Electricity proximity alarm event',
                                                   'modbus_enable': '1',
                                                   'modbus_table': 'holding',
                                                   'modbus_register_count': '1',
                                                   'modbus_mapping_mode': 'single',
                                                   'modbus_scale': '1',
                                                   'bacnet_enable': '1',
                                                   'bacnet_object_type': 'BI',
                                                   'bacnet_unit': '95'},
                'impactAlarmEvent': {'name': 'impactAlarmEvent',
                                     'json_key': 'impactAlarmEvent',
                                     'data_type': 'bool',
                                     'unit': 'none',
                                     'readwrite': '0',
                                     'description': 'Impact detection alarm event',
                                     'modbus_enable': '1',
                                     'modbus_table': 'holding',
                                     'modbus_register_count': '1',
                                     'modbus_mapping_mode': 'single',
                                     'modbus_scale': '1',
                                     'bacnet_enable': '1',
                                     'bacnet_object_type': 'BI',
                                     'bacnet_unit': '95'},
                'silenceAlarmEvent': {'name': 'silenceAlarmEvent',
                                      'json_key': 'silenceAlarmEvent',
                                      'data_type': 'bool',
                                      'unit': 'none',
                                      'readwrite': '0',
                                      'description': 'Silence alarm event',
                                      'modbus_enable': '1',
                                      'modbus_table': 'holding',
                                      'modbus_register_count': '1',
                                      'modbus_mapping_mode': 'single',
                                      'modbus_scale': '1',
                                      'bacnet_enable': '1',
                                      'bacnet_object_type': 'BI',
                                      'bacnet_unit': '95'},
                'alarmEventActive': {'name': 'alarmEventActive',
                                     'json_key': 'alarmEventActive',
                                     'data_type': 'bool',
                                     'unit': 'none',
                                     'readwrite': '0',
                                     'description': 'General alarm event active flag',
                                     'modbus_enable': '1',
                                     'modbus_table': 'holding',
                                     'modbus_register_count': '1',
                                     'modbus_mapping_mode': 'single',
                                     'modbus_scale': '1',
                                     'bacnet_enable': '1',
                                     'bacnet_object_type': 'BI',
                                     'bacnet_unit': '95'},
                'impactAlarmStatus': {'name': 'impactAlarmStatus',
                                      'json_key': 'impactAlarmStatus',
                                      'data_type': 'bool',
                                      'unit': 'none',
                                      'readwrite': '0',
                                      'description': 'Impact alarm status',
                                      'modbus_enable': '1',
                                      'modbus_table': 'holding',
                                      'modbus_register_count': '1',
                                      'modbus_mapping_mode': 'single',
                                      'modbus_scale': '1',
                                      'bacnet_enable': '1',
                                      'bacnet_object_type': 'BI',
                                      'bacnet_unit': '95'},
                'silenceAlarmStatus': {'name': 'silenceAlarmStatus',
                                       'json_key': 'silenceAlarmStatus',
                                       'data_type': 'bool',
                                       'unit': 'none',
                                       'readwrite': '0',
                                       'description': 'Silence alarm status',
                                       'modbus_enable': '1',
                                       'modbus_table': 'holding',
                                       'modbus_register_count': '1',
                                       'modbus_mapping_mode': 'single',
                                       'modbus_scale': '1',
                                       'bacnet_enable': '1',
                                       'bacnet_object_type': 'BI',
                                       'bacnet_unit': '95'},
                'heightAccessAlarmStatus': {'name': 'heightAccessAlarmStatus',
                                            'json_key': 'heightAccessAlarmStatus',
                                            'data_type': 'bool',
                                            'unit': 'none',
                                            'readwrite': '0',
                                            'description': 'Height access alarm status',
                                            'modbus_enable': '1',
                                            'modbus_table': 'holding',
                                            'modbus_register_count': '1',
                                            'modbus_mapping_mode': 'single',
                                            'modbus_scale': '1',
                                            'bacnet_enable': '1',
                                            'bacnet_object_type': 'BI',
                                            'bacnet_unit': '95'},
                'heightAccessAlarmEvent': {'name': 'heightAccessAlarmEvent',
                                           'json_key': 'heightAccessAlarmEvent',
                                           'data_type': 'bool',
                                           'unit': 'none',
                                           'readwrite': '0',
                                           'description': 'Height access alarm event',
                                           'modbus_enable': '1',
                                           'modbus_table': 'holding',
                                           'modbus_register_count': '1',
                                           'modbus_mapping_mode': 'single',
                                           'modbus_scale': '1',
                                           'bacnet_enable': '1',
                                           'bacnet_object_type': 'BI',
                                           'bacnet_unit': '95'},
                'switchTimerStatus': {'name': 'switchTimerStatus',
                                      'json_key': 'switchTimerStatus',
                                      'data_type': 'int',
                                      'unit': 'none',
                                      'readwrite': '0',
                                      'min_value': '0',
                                      'max_value': '4294967295',
                                      'description': 'Switch timer status bitfield',
                                      'modbus_enable': '1',
                                      'modbus_table': 'holding',
                                      'modbus_register_count': '2',
                                      'modbus_mapping_mode': 'big_endian',
                                      'modbus_scale': '1',
                                      'bacnet_enable': '1',
                                      'bacnet_object_type': 'AI',
                                      'bacnet_unit': '95'},
                'ds103ControlTarget': {'name': 'ds103ControlTarget',
                                       'json_key': 'ds103ControlTarget',
                                       'data_type': 'int',
                                       'unit': 'none',
                                       'min_value': '1',
                                       'max_value': '255',
                                       'readwrite': '1',
                                       'description': 'DS-103 control target (1=left, 2=middle, 3=right, 254=lock, '
                                                      '255=all switches)',
                                       'modbus_enable': '1',
                                       'modbus_table': 'holding',
                                       'modbus_register_count': '1',
                                       'modbus_mapping_mode': 'single',
                                       'modbus_scale': '1',
                                       'bacnet_enable': '1',
                                       'bacnet_object_type': 'AV',
                                       'bacnet_unit': '95'},
                'ds103ControlState': {'name': 'ds103ControlState',
                                      'json_key': 'ds103ControlState',
                                      'data_type': 'bool',
                                      'unit': 'none',
                                      'readwrite': '1',
                                      'description': 'DS-103 control state (switch: 0=off,1=on; lock: 0=unlock,1=lock)',
                                      'modbus_enable': '1',
                                      'modbus_table': 'holding',
                                      'modbus_register_count': '1',
                                      'modbus_mapping_mode': 'single',
                                      'modbus_scale': '1',
                                      'bacnet_enable': '1',
                                      'bacnet_object_type': 'BV',
                                      'bacnet_unit': '95'},
                'ds103ControlMode': {'name': 'ds103ControlMode',
                                     'json_key': 'ds103ControlMode',
                                     'data_type': 'int',
                                     'unit': 'none',
                                     'min_value': '0',
                                     'max_value': '4',
                                     'readwrite': '1',
                                     'description': 'DS-103 control mode (0=immediate, 1=delay, 2=schedule, '
                                                    '3=cancelTimer, 4=query)',
                                     'modbus_enable': '1',
                                     'modbus_table': 'holding',
                                     'modbus_register_count': '1',
                                     'modbus_mapping_mode': 'single',
                                     'modbus_scale': '1',
                                     'bacnet_enable': '1',
                                     'bacnet_object_type': 'AV',
                                     'bacnet_unit': '95'},
                'ds103DelaySeconds': {'name': 'ds103DelaySeconds',
                                      'json_key': 'ds103DelaySeconds',
                                      'data_type': 'int',
                                      'unit': 'seconds',
                                      'min_value': '0',
                                      'max_value': '4294967295',
                                      'readwrite': '1',
                                      'description': 'DS-103 delay time in seconds for delayed commands',
                                      'modbus_enable': '1',
                                      'modbus_table': 'holding',
                                      'modbus_register_count': '2',
                                      'modbus_mapping_mode': 'big_endian',
                                      'modbus_scale': '1',
                                      'bacnet_enable': '1',
                                      'bacnet_object_type': 'AV',
                                      'bacnet_unit': '73'},
                'ds103ScheduleTimestamp': {'name': 'ds103ScheduleTimestamp',
                                           'json_key': 'ds103ScheduleTimestamp',
                                           'data_type': 'timestamp',
                                           'unit': 'seconds',
                                           'min_value': '0',
                                           'max_value': '4294967295',
                                           'readwrite': '1',
                                           'description': 'DS-103 scheduled execution timestamp in Unix seconds',
                                           'modbus_enable': '1',
                                           'modbus_table': 'holding',
                                           'modbus_register_count': '2',
                                           'modbus_mapping_mode': 'big_endian',
                                           'modbus_scale': '1',
                                           'bacnet_enable': '1',
                                           'bacnet_object_type': 'AV',
                                           'bacnet_unit': '73'},
                'ds103RepeatDaily': {'name': 'ds103RepeatDaily',
                                     'json_key': 'ds103RepeatDaily',
                                     'data_type': 'bool',
                                     'unit': 'none',
                                     'readwrite': '1',
                                     'description': 'DS-103 schedule repeat mode (0=once, 1=daily)',
                                     'modbus_enable': '1',
                                     'modbus_table': 'holding',
                                     'modbus_register_count': '1',
                                     'modbus_mapping_mode': 'single',
                                     'modbus_scale': '1',
                                     'bacnet_enable': '1',
                                     'bacnet_object_type': 'BV',
                                     'bacnet_unit': '95'},
                'ds501ControlTarget': {'name': 'ds501ControlTarget',
                                       'json_key': 'ds501ControlTarget',
                                       'data_type': 'int',
                                       'unit': 'none',
                                       'min_value': '1',
                                       'max_value': '255',
                                       'readwrite': '1',
                                       'description': 'DS-501 control target (1=socket, 254=lock, 255=query)',
                                       'modbus_enable': '1',
                                       'modbus_table': 'holding',
                                       'modbus_register_count': '1',
                                       'modbus_mapping_mode': 'single',
                                       'modbus_scale': '1',
                                       'bacnet_enable': '1',
                                       'bacnet_object_type': 'AV',
                                       'bacnet_unit': '95'},
                'ds501ControlState': {'name': 'ds501ControlState',
                                      'json_key': 'ds501ControlState',
                                      'data_type': 'bool',
                                      'unit': 'none',
                                      'readwrite': '1',
                                      'description': 'DS-501 control state (socket: 0=off,1=on; lock: 0=unlock,1=lock)',
                                      'modbus_enable': '1',
                                      'modbus_table': 'holding',
                                      'modbus_register_count': '1',
                                      'modbus_mapping_mode': 'single',
                                      'modbus_scale': '1',
                                      'bacnet_enable': '1',
                                      'bacnet_object_type': 'BV',
                                      'bacnet_unit': '95'},
                'ds501ControlMode': {'name': 'ds501ControlMode',
                                     'json_key': 'ds501ControlMode',
                                     'data_type': 'int',
                                     'unit': 'none',
                                     'min_value': '0',
                                     'max_value': '4',
                                     'readwrite': '1',
                                     'description': 'DS-501 control mode (0=immediate, 1=delay, 2=schedule, '
                                                    '3=cancelTimer, 4=query)',
                                     'modbus_enable': '1',
                                     'modbus_table': 'holding',
                                     'modbus_register_count': '1',
                                     'modbus_mapping_mode': 'single',
                                     'modbus_scale': '1',
                                     'bacnet_enable': '1',
                                     'bacnet_object_type': 'AV',
                                     'bacnet_unit': '95'},
                'ds501DelaySeconds': {'name': 'ds501DelaySeconds',
                                      'json_key': 'ds501DelaySeconds',
                                      'data_type': 'int',
                                      'unit': 'seconds',
                                      'min_value': '0',
                                      'max_value': '4294967295',
                                      'readwrite': '1',
                                      'description': 'DS-501 delay time in seconds for delayed commands',
                                      'modbus_enable': '1',
                                      'modbus_table': 'holding',
                                      'modbus_register_count': '2',
                                      'modbus_mapping_mode': 'big_endian',
                                      'modbus_scale': '1',
                                      'bacnet_enable': '1',
                                      'bacnet_object_type': 'AV',
                                      'bacnet_unit': '73'},
                'ds501ScheduleTimestamp': {'name': 'ds501ScheduleTimestamp',
                                           'json_key': 'ds501ScheduleTimestamp',
                                           'data_type': 'timestamp',
                                           'unit': 'seconds',
                                           'min_value': '0',
                                           'max_value': '4294967295',
                                           'readwrite': '1',
                                           'description': 'DS-501 scheduled execution timestamp in Unix seconds',
                                           'modbus_enable': '1',
                                           'modbus_table': 'holding',
                                           'modbus_register_count': '2',
                                           'modbus_mapping_mode': 'big_endian',
                                           'modbus_scale': '1',
                                           'bacnet_enable': '1',
                                           'bacnet_object_type': 'AV',
                                           'bacnet_unit': '73'},
                'ds501RepeatDaily': {'name': 'ds501RepeatDaily',
                                     'json_key': 'ds501RepeatDaily',
                                     'data_type': 'bool',
                                     'unit': 'none',
                                     'readwrite': '1',
                                     'description': 'DS-501 schedule repeat mode (0=once, 1=daily)',
                                     'modbus_enable': '1',
                                     'modbus_table': 'holding',
                                     'modbus_register_count': '1',
                                     'modbus_mapping_mode': 'single',
                                     'modbus_scale': '1',
                                     'bacnet_enable': '1',
                                     'bacnet_object_type': 'BV',
                                     'bacnet_unit': '95'},
                'currentAvg': {'name': 'currentAvg',
                               'json_key': 'currentAvg',
                               'data_type': 'float',
                               'unit': 'ampere',
                               'decimal_places': '1',
                               'min_value': '0',
                               'max_value': '100',
                               'readwrite': '0',
                               'description': 'Average three-phase current',
                               'modbus_enable': '1',
                               'modbus_table': 'holding',
                               'modbus_register_count': '1',
                               'modbus_mapping_mode': 'single',
                               'modbus_scale': '10',
                               'bacnet_enable': '1',
                               'bacnet_object_type': 'AI',
                               'bacnet_unit': '3'},
                'activePowerB': {'name': 'activePowerB',
                                 'json_key': 'activePowerB',
                                 'data_type': 'float',
                                 'unit': 'watt',
                                 'decimal_places': '2',
                                 'min_value': '0',
                                 'max_value': '10000',
                                 'readwrite': '0',
                                 'description': 'B-phase active power',
                                 'modbus_enable': '1',
                                 'modbus_table': 'holding',
                                 'modbus_register_count': '2',
                                 'modbus_mapping_mode': 'big_endian',
                                 'modbus_scale': '1',
                                 'bacnet_enable': '1',
                                 'bacnet_object_type': 'AI',
                                 'bacnet_unit': '47'},
                'activePowerC': {'name': 'activePowerC',
                                 'json_key': 'activePowerC',
                                 'data_type': 'float',
                                 'unit': 'watt',
                                 'decimal_places': '2',
                                 'min_value': '0',
                                 'max_value': '10000',
                                 'readwrite': '0',
                                 'description': 'C-phase active power',
                                 'modbus_enable': '1',
                                 'modbus_table': 'holding',
                                 'modbus_register_count': '2',
                                 'modbus_mapping_mode': 'big_endian',
                                 'modbus_scale': '1',
                                 'bacnet_enable': '1',
                                 'bacnet_object_type': 'AI',
                                 'bacnet_unit': '47'},
                'reactivePowerA': {'name': 'reactivePowerA',
                                   'json_key': 'reactivePowerA',
                                   'data_type': 'float',
                                   'unit': 'none',
                                   'decimal_places': '2',
                                   'min_value': '-10000',
                                   'max_value': '10000',
                                   'readwrite': '0',
                                   'description': 'A-phase reactive power',
                                   'modbus_enable': '1',
                                   'modbus_table': 'holding',
                                   'modbus_register_count': '2',
                                   'modbus_mapping_mode': 'big_endian',
                                   'modbus_scale': '1',
                                   'bacnet_enable': '1',
                                   'bacnet_object_type': 'AI',
                                   'bacnet_unit': '11'},
                'reactivePowerB': {'name': 'reactivePowerB',
                                   'json_key': 'reactivePowerB',
                                   'data_type': 'float',
                                   'unit': 'none',
                                   'decimal_places': '2',
                                   'min_value': '-10000',
                                   'max_value': '10000',
                                   'readwrite': '0',
                                   'description': 'B-phase reactive power',
                                   'modbus_enable': '1',
                                   'modbus_table': 'holding',
                                   'modbus_register_count': '2',
                                   'modbus_mapping_mode': 'big_endian',
                                   'modbus_scale': '1',
                                   'bacnet_enable': '1',
                                   'bacnet_object_type': 'AI',
                                   'bacnet_unit': '11'},
                'reactivePowerC': {'name': 'reactivePowerC',
                                   'json_key': 'reactivePowerC',
                                   'data_type': 'float',
                                   'unit': 'none',
                                   'decimal_places': '2',
                                   'min_value': '-10000',
                                   'max_value': '10000',
                                   'readwrite': '0',
                                   'description': 'C-phase reactive power',
                                   'modbus_enable': '1',
                                   'modbus_table': 'holding',
                                   'modbus_register_count': '2',
                                   'modbus_mapping_mode': 'big_endian',
                                   'modbus_scale': '1',
                                   'bacnet_enable': '1',
                                   'bacnet_object_type': 'AI',
                                   'bacnet_unit': '11'},
                'reactivePowerTotal': {'name': 'reactivePowerTotal',
                                       'json_key': 'reactivePowerTotal',
                                       'data_type': 'float',
                                       'unit': 'none',
                                       'decimal_places': '2',
                                       'min_value': '-30000',
                                       'max_value': '30000',
                                       'readwrite': '0',
                                       'description': 'Total reactive power',
                                       'modbus_enable': '1',
                                       'modbus_table': 'holding',
                                       'modbus_register_count': '2',
                                       'modbus_mapping_mode': 'big_endian',
                                       'modbus_scale': '1',
                                       'bacnet_enable': '1',
                                       'bacnet_object_type': 'AI',
                                       'bacnet_unit': '11'},
                'apparentPowerA': {'name': 'apparentPowerA',
                                   'json_key': 'apparentPowerA',
                                   'data_type': 'float',
                                   'unit': 'none',
                                   'decimal_places': '2',
                                   'min_value': '0',
                                   'max_value': '10000',
                                   'readwrite': '0',
                                   'description': 'A-phase apparent power',
                                   'modbus_enable': '1',
                                   'modbus_table': 'holding',
                                   'modbus_register_count': '2',
                                   'modbus_mapping_mode': 'big_endian',
                                   'modbus_scale': '1',
                                   'bacnet_enable': '1',
                                   'bacnet_object_type': 'AI',
                                   'bacnet_unit': '8'},
                'apparentPowerB': {'name': 'apparentPowerB',
                                   'json_key': 'apparentPowerB',
                                   'data_type': 'float',
                                   'unit': 'none',
                                   'decimal_places': '2',
                                   'min_value': '0',
                                   'max_value': '10000',
                                   'readwrite': '0',
                                   'description': 'B-phase apparent power',
                                   'modbus_enable': '1',
                                   'modbus_table': 'holding',
                                   'modbus_register_count': '2',
                                   'modbus_mapping_mode': 'big_endian',
                                   'modbus_scale': '1',
                                   'bacnet_enable': '1',
                                   'bacnet_object_type': 'AI',
                                   'bacnet_unit': '8'},
                'apparentPowerC': {'name': 'apparentPowerC',
                                   'json_key': 'apparentPowerC',
                                   'data_type': 'float',
                                   'unit': 'none',
                                   'decimal_places': '2',
                                   'min_value': '0',
                                   'max_value': '10000',
                                   'readwrite': '0',
                                   'description': 'C-phase apparent power',
                                   'modbus_enable': '1',
                                   'modbus_table': 'holding',
                                   'modbus_register_count': '2',
                                   'modbus_mapping_mode': 'big_endian',
                                   'modbus_scale': '1',
                                   'bacnet_enable': '1',
                                   'bacnet_object_type': 'AI',
                                   'bacnet_unit': '8'},
                'apparentPowerTotal': {'name': 'apparentPowerTotal',
                                       'json_key': 'apparentPowerTotal',
                                       'data_type': 'float',
                                       'unit': 'none',
                                       'decimal_places': '2',
                                       'min_value': '0',
                                       'max_value': '30000',
                                       'readwrite': '0',
                                       'description': 'Total apparent power',
                                       'modbus_enable': '1',
                                       'modbus_table': 'holding',
                                       'modbus_register_count': '2',
                                       'modbus_mapping_mode': 'big_endian',
                                       'modbus_scale': '1',
                                       'bacnet_enable': '1',
                                       'bacnet_object_type': 'AI',
                                       'bacnet_unit': '8'},
                'powerFactorA': {'name': 'powerFactorA',
                                 'json_key': 'powerFactorA',
                                 'data_type': 'float',
                                 'unit': 'none',
                                 'decimal_places': '3',
                                 'min_value': '0',
                                 'max_value': '1',
                                 'readwrite': '0',
                                 'description': 'A-phase power factor',
                                 'modbus_enable': '1',
                                 'modbus_table': 'holding',
                                 'modbus_register_count': '2',
                                 'modbus_mapping_mode': 'big_endian',
                                 'modbus_scale': '1',
                                 'bacnet_enable': '1',
                                 'bacnet_object_type': 'AI',
                                 'bacnet_unit': '95'},
                'powerFactorB': {'name': 'powerFactorB',
                                 'json_key': 'powerFactorB',
                                 'data_type': 'float',
                                 'unit': 'none',
                                 'decimal_places': '3',
                                 'min_value': '0',
                                 'max_value': '1',
                                 'readwrite': '0',
                                 'description': 'B-phase power factor',
                                 'modbus_enable': '1',
                                 'modbus_table': 'holding',
                                 'modbus_register_count': '2',
                                 'modbus_mapping_mode': 'big_endian',
                                 'modbus_scale': '1',
                                 'bacnet_enable': '1',
                                 'bacnet_object_type': 'AI',
                                 'bacnet_unit': '95'},
                'powerFactorC': {'name': 'powerFactorC',
                                 'json_key': 'powerFactorC',
                                 'data_type': 'float',
                                 'unit': 'none',
                                 'decimal_places': '3',
                                 'min_value': '0',
                                 'max_value': '1',
                                 'readwrite': '0',
                                 'description': 'C-phase power factor',
                                 'modbus_enable': '1',
                                 'modbus_table': 'holding',
                                 'modbus_register_count': '2',
                                 'modbus_mapping_mode': 'big_endian',
                                 'modbus_scale': '1',
                                 'bacnet_enable': '1',
                                 'bacnet_object_type': 'AI',
                                 'bacnet_unit': '95'},
                'reactiveEnergy': {'name': 'reactiveEnergy',
                                   'json_key': 'reactiveEnergy',
                                   'data_type': 'float',
                                   'unit': 'none',
                                   'decimal_places': '2',
                                   'min_value': '0',
                                   'max_value': '999999',
                                   'readwrite': '0',
                                   'description': 'Reactive energy consumption',
                                   'modbus_enable': '1',
                                   'modbus_table': 'holding',
                                   'modbus_register_count': '2',
                                   'modbus_mapping_mode': 'big_endian',
                                   'modbus_scale': '1',
                                   'bacnet_enable': '1',
                                   'bacnet_object_type': 'AI',
                                   'bacnet_unit': '204'},
                'apparentEnergy': {'name': 'apparentEnergy',
                                   'json_key': 'apparentEnergy',
                                   'data_type': 'float',
                                   'unit': 'none',
                                   'decimal_places': '2',
                                   'min_value': '0',
                                   'max_value': '999999',
                                   'readwrite': '0',
                                   'description': 'Apparent energy consumption',
                                   'modbus_enable': '1',
                                   'modbus_table': 'holding',
                                   'modbus_register_count': '2',
                                   'modbus_mapping_mode': 'big_endian',
                                   'modbus_scale': '1',
                                   'bacnet_enable': '1',
                                   'bacnet_object_type': 'AI',
                                   'bacnet_unit': '240'},
                'tempSensor2': {'name': 'tempSensor2',
                                'json_key': 'tempSensor2',
                                'data_type': 'float',
                                'unit': 'celsius',
                                'decimal_places': '1',
                                'min_value': '-20',
                                'max_value': '110',
                                'readwrite': '0',
                                'description': 'Temperature sensor 2',
                                'modbus_enable': '1',
                                'modbus_table': 'holding',
                                'modbus_register_count': '1',
                                'modbus_mapping_mode': 'single',
                                'modbus_scale': '10',
                                'bacnet_enable': '1',
                                'bacnet_object_type': 'AI',
                                'bacnet_unit': '62'},
                'tempSensor3': {'name': 'tempSensor3',
                                'json_key': 'tempSensor3',
                                'data_type': 'float',
                                'unit': 'celsius',
                                'decimal_places': '1',
                                'min_value': '-20',
                                'max_value': '110',
                                'readwrite': '0',
                                'description': 'Temperature sensor 3',
                                'modbus_enable': '1',
                                'modbus_table': 'holding',
                                'modbus_register_count': '1',
                                'modbus_mapping_mode': 'single',
                                'modbus_scale': '10',
                                'bacnet_enable': '1',
                                'bacnet_object_type': 'AI',
                                'bacnet_unit': '62'},
                'tempSensor4': {'name': 'tempSensor4',
                                'json_key': 'tempSensor4',
                                'data_type': 'float',
                                'unit': 'celsius',
                                'decimal_places': '1',
                                'min_value': '-20',
                                'max_value': '110',
                                'readwrite': '0',
                                'description': 'Temperature sensor 4',
                                'modbus_enable': '1',
                                'modbus_table': 'holding',
                                'modbus_register_count': '1',
                                'modbus_mapping_mode': 'single',
                                'modbus_scale': '10',
                                'bacnet_enable': '1',
                                'bacnet_object_type': 'AI',
                                'bacnet_unit': '62'},
                'alarmOvercurrentB': {'name': 'alarmOvercurrentB',
                                      'json_key': 'alarmOvercurrentB',
                                      'data_type': 'bool',
                                      'unit': 'none',
                                      'readwrite': '0',
                                      'description': 'B-phase overcurrent alarm',
                                      'modbus_enable': '1',
                                      'modbus_table': 'holding',
                                      'modbus_register_count': '1',
                                      'modbus_mapping_mode': 'single',
                                      'modbus_scale': '1',
                                      'bacnet_enable': '1',
                                      'bacnet_object_type': 'BI',
                                      'bacnet_unit': '95'},
                'alarmOvercurrentC': {'name': 'alarmOvercurrentC',
                                      'json_key': 'alarmOvercurrentC',
                                      'data_type': 'bool',
                                      'unit': 'none',
                                      'readwrite': '0',
                                      'description': 'C-phase overcurrent alarm',
                                      'modbus_enable': '1',
                                      'modbus_table': 'holding',
                                      'modbus_register_count': '1',
                                      'modbus_mapping_mode': 'single',
                                      'modbus_scale': '1',
                                      'bacnet_enable': '1',
                                      'bacnet_object_type': 'BI',
                                      'bacnet_unit': '95'},
                'alarmOvervoltageA': {'name': 'alarmOvervoltageA',
                                      'json_key': 'alarmOvervoltageA',
                                      'data_type': 'bool',
                                      'unit': 'none',
                                      'readwrite': '0',
                                      'description': 'A-phase overvoltage alarm',
                                      'modbus_enable': '1',
                                      'modbus_table': 'holding',
                                      'modbus_register_count': '1',
                                      'modbus_mapping_mode': 'single',
                                      'modbus_scale': '1',
                                      'bacnet_enable': '1',
                                      'bacnet_object_type': 'BI',
                                      'bacnet_unit': '95'},
                'alarmOvervoltageB': {'name': 'alarmOvervoltageB',
                                      'json_key': 'alarmOvervoltageB',
                                      'data_type': 'bool',
                                      'unit': 'none',
                                      'readwrite': '0',
                                      'description': 'B-phase overvoltage alarm',
                                      'modbus_enable': '1',
                                      'modbus_table': 'holding',
                                      'modbus_register_count': '1',
                                      'modbus_mapping_mode': 'single',
                                      'modbus_scale': '1',
                                      'bacnet_enable': '1',
                                      'bacnet_object_type': 'BI',
                                      'bacnet_unit': '95'},
                'alarmOvervoltageC': {'name': 'alarmOvervoltageC',
                                      'json_key': 'alarmOvervoltageC',
                                      'data_type': 'bool',
                                      'unit': 'none',
                                      'readwrite': '0',
                                      'description': 'C-phase overvoltage alarm',
                                      'modbus_enable': '1',
                                      'modbus_table': 'holding',
                                      'modbus_register_count': '1',
                                      'modbus_mapping_mode': 'single',
                                      'modbus_scale': '1',
                                      'bacnet_enable': '1',
                                      'bacnet_object_type': 'BI',
                                      'bacnet_unit': '95'},
                'alarmUndervoltageA': {'name': 'alarmUndervoltageA',
                                       'json_key': 'alarmUndervoltageA',
                                       'data_type': 'bool',
                                       'unit': 'none',
                                       'readwrite': '0',
                                       'description': 'A-phase undervoltage alarm',
                                       'modbus_enable': '1',
                                       'modbus_table': 'holding',
                                       'modbus_register_count': '1',
                                       'modbus_mapping_mode': 'single',
                                       'modbus_scale': '1',
                                       'bacnet_enable': '1',
                                       'bacnet_object_type': 'BI',
                                       'bacnet_unit': '95'},
                'alarmUndervoltageB': {'name': 'alarmUndervoltageB',
                                       'json_key': 'alarmUndervoltageB',
                                       'data_type': 'bool',
                                       'unit': 'none',
                                       'readwrite': '0',
                                       'description': 'B-phase undervoltage alarm',
                                       'modbus_enable': '1',
                                       'modbus_table': 'holding',
                                       'modbus_register_count': '1',
                                       'modbus_mapping_mode': 'single',
                                       'modbus_scale': '1',
                                       'bacnet_enable': '1',
                                       'bacnet_object_type': 'BI',
                                       'bacnet_unit': '95'},
                'alarmUndervoltageC': {'name': 'alarmUndervoltageC',
                                       'json_key': 'alarmUndervoltageC',
                                       'data_type': 'bool',
                                       'unit': 'none',
                                       'readwrite': '0',
                                       'description': 'C-phase undervoltage alarm',
                                       'modbus_enable': '1',
                                       'modbus_table': 'holding',
                                       'modbus_register_count': '1',
                                       'modbus_mapping_mode': 'single',
                                       'modbus_scale': '1',
                                       'bacnet_enable': '1',
                                       'bacnet_object_type': 'BI',
                                       'bacnet_unit': '95'},
                'alarmShortCircuit': {'name': 'alarmShortCircuit',
                                      'json_key': 'alarmShortCircuit',
                                      'data_type': 'bool',
                                      'unit': 'none',
                                      'readwrite': '0',
                                      'description': 'Short circuit alarm',
                                      'modbus_enable': '1',
                                      'modbus_table': 'holding',
                                      'modbus_register_count': '1',
                                      'modbus_mapping_mode': 'single',
                                      'modbus_scale': '1',
                                      'bacnet_enable': '1',
                                      'bacnet_object_type': 'BI',
                                      'bacnet_unit': '95'},
                'alarmTempSensor1': {'name': 'alarmTempSensor1',
                                     'json_key': 'alarmTempSensor1',
                                     'data_type': 'bool',
                                     'unit': 'none',
                                     'readwrite': '0',
                                     'description': 'Temperature sensor 1 alarm',
                                     'modbus_enable': '1',
                                     'modbus_table': 'holding',
                                     'modbus_register_count': '1',
                                     'modbus_mapping_mode': 'single',
                                     'modbus_scale': '1',
                                     'bacnet_enable': '1',
                                     'bacnet_object_type': 'BI',
                                     'bacnet_unit': '95'},
                'alarmTempSensor2': {'name': 'alarmTempSensor2',
                                     'json_key': 'alarmTempSensor2',
                                     'data_type': 'bool',
                                     'unit': 'none',
                                     'readwrite': '0',
                                     'description': 'Temperature sensor 2 alarm',
                                     'modbus_enable': '1',
                                     'modbus_table': 'holding',
                                     'modbus_register_count': '1',
                                     'modbus_mapping_mode': 'single',
                                     'modbus_scale': '1',
                                     'bacnet_enable': '1',
                                     'bacnet_object_type': 'BI',
                                     'bacnet_unit': '95'},
                'alarmTempSensor3': {'name': 'alarmTempSensor3',
                                     'json_key': 'alarmTempSensor3',
                                     'data_type': 'bool',
                                     'unit': 'none',
                                     'readwrite': '0',
                                     'description': 'Temperature sensor 3 alarm',
                                     'modbus_enable': '1',
                                     'modbus_table': 'holding',
                                     'modbus_register_count': '1',
                                     'modbus_mapping_mode': 'single',
                                     'modbus_scale': '1',
                                     'bacnet_enable': '1',
                                     'bacnet_object_type': 'BI',
                                     'bacnet_unit': '95'},
                'alarmTempSensor4': {'name': 'alarmTempSensor4',
                                     'json_key': 'alarmTempSensor4',
                                     'data_type': 'bool',
                                     'unit': 'none',
                                     'readwrite': '0',
                                     'description': 'Temperature sensor 4 alarm',
                                     'modbus_enable': '1',
                                     'modbus_table': 'holding',
                                     'modbus_register_count': '1',
                                     'modbus_mapping_mode': 'single',
                                     'modbus_scale': '1',
                                     'bacnet_enable': '1',
                                     'bacnet_object_type': 'BI',
                                     'bacnet_unit': '95'},
                'beaconRefRssi': {'name': 'beaconRefRssi',
                                  'json_key': 'beaconRefRssi',
                                  'data_type': 'int',
                                  'unit': 'none',
                                  'min_value': '-120',
                                  'max_value': '0',
                                  'readwrite': '0',
                                  'description': 'Latest beacon 1m reference RSSI',
                                  'modbus_enable': '1',
                                  'modbus_table': 'holding',
                                  'modbus_register_count': '1',
                                  'modbus_mapping_mode': 'single',
                                  'modbus_scale': '1',
                                  'bacnet_enable': '1',
                                  'bacnet_object_type': 'AI',
                                  'bacnet_unit': '95'},
                'electricalAlarmEvent': {'name': 'electricalAlarmEvent',
                                         'json_key': 'electricalAlarmEvent',
                                         'data_type': 'int',
                                         'unit': 'none',
                                         'min_value': '0',
                                         'max_value': '65535',
                                         'readwrite': '0',
                                         'description': 'Electrical fire alarm event bitfield',
                                         'modbus_enable': '1',
                                         'modbus_table': 'holding',
                                         'modbus_register_count': '1',
                                         'modbus_mapping_mode': 'single',
                                         'modbus_scale': '1',
                                         'bacnet_enable': '1',
                                         'bacnet_object_type': 'AI',
                                         'bacnet_unit': '95'},
                'alarmOvercurrentAEvent': {'name': 'alarmOvercurrentAEvent',
                                           'json_key': 'alarmOvercurrentAEvent',
                                           'data_type': 'bool',
                                           'unit': 'none',
                                           'readwrite': '0',
                                           'description': 'A-phase overcurrent alarm event',
                                           'modbus_enable': '1',
                                           'modbus_table': 'holding',
                                           'modbus_register_count': '1',
                                           'modbus_mapping_mode': 'single',
                                           'modbus_scale': '1',
                                           'bacnet_enable': '1',
                                           'bacnet_object_type': 'BI',
                                           'bacnet_unit': '95'},
                'alarmOvercurrentBEvent': {'name': 'alarmOvercurrentBEvent',
                                           'json_key': 'alarmOvercurrentBEvent',
                                           'data_type': 'bool',
                                           'unit': 'none',
                                           'readwrite': '0',
                                           'description': 'B-phase overcurrent alarm event',
                                           'modbus_enable': '1',
                                           'modbus_table': 'holding',
                                           'modbus_register_count': '1',
                                           'modbus_mapping_mode': 'single',
                                           'modbus_scale': '1',
                                           'bacnet_enable': '1',
                                           'bacnet_object_type': 'BI',
                                           'bacnet_unit': '95'},
                'alarmOvercurrentCEvent': {'name': 'alarmOvercurrentCEvent',
                                           'json_key': 'alarmOvercurrentCEvent',
                                           'data_type': 'bool',
                                           'unit': 'none',
                                           'readwrite': '0',
                                           'description': 'C-phase overcurrent alarm event',
                                           'modbus_enable': '1',
                                           'modbus_table': 'holding',
                                           'modbus_register_count': '1',
                                           'modbus_mapping_mode': 'single',
                                           'modbus_scale': '1',
                                           'bacnet_enable': '1',
                                           'bacnet_object_type': 'BI',
                                           'bacnet_unit': '95'},
                'alarmOvervoltageAEvent': {'name': 'alarmOvervoltageAEvent',
                                           'json_key': 'alarmOvervoltageAEvent',
                                           'data_type': 'bool',
                                           'unit': 'none',
                                           'readwrite': '0',
                                           'description': 'A-phase overvoltage alarm event',
                                           'modbus_enable': '1',
                                           'modbus_table': 'holding',
                                           'modbus_register_count': '1',
                                           'modbus_mapping_mode': 'single',
                                           'modbus_scale': '1',
                                           'bacnet_enable': '1',
                                           'bacnet_object_type': 'BI',
                                           'bacnet_unit': '95'},
                'alarmOvervoltageBEvent': {'name': 'alarmOvervoltageBEvent',
                                           'json_key': 'alarmOvervoltageBEvent',
                                           'data_type': 'bool',
                                           'unit': 'none',
                                           'readwrite': '0',
                                           'description': 'B-phase overvoltage alarm event',
                                           'modbus_enable': '1',
                                           'modbus_table': 'holding',
                                           'modbus_register_count': '1',
                                           'modbus_mapping_mode': 'single',
                                           'modbus_scale': '1',
                                           'bacnet_enable': '1',
                                           'bacnet_object_type': 'BI',
                                           'bacnet_unit': '95'},
                'alarmOvervoltageCEvent': {'name': 'alarmOvervoltageCEvent',
                                           'json_key': 'alarmOvervoltageCEvent',
                                           'data_type': 'bool',
                                           'unit': 'none',
                                           'readwrite': '0',
                                           'description': 'C-phase overvoltage alarm event',
                                           'modbus_enable': '1',
                                           'modbus_table': 'holding',
                                           'modbus_register_count': '1',
                                           'modbus_mapping_mode': 'single',
                                           'modbus_scale': '1',
                                           'bacnet_enable': '1',
                                           'bacnet_object_type': 'BI',
                                           'bacnet_unit': '95'},
                'alarmUndervoltageAEvent': {'name': 'alarmUndervoltageAEvent',
                                            'json_key': 'alarmUndervoltageAEvent',
                                            'data_type': 'bool',
                                            'unit': 'none',
                                            'readwrite': '0',
                                            'description': 'A-phase undervoltage alarm event',
                                            'modbus_enable': '1',
                                            'modbus_table': 'holding',
                                            'modbus_register_count': '1',
                                            'modbus_mapping_mode': 'single',
                                            'modbus_scale': '1',
                                            'bacnet_enable': '1',
                                            'bacnet_object_type': 'BI',
                                            'bacnet_unit': '95'},
                'alarmUndervoltageBEvent': {'name': 'alarmUndervoltageBEvent',
                                            'json_key': 'alarmUndervoltageBEvent',
                                            'data_type': 'bool',
                                            'unit': 'none',
                                            'readwrite': '0',
                                            'description': 'B-phase undervoltage alarm event',
                                            'modbus_enable': '1',
                                            'modbus_table': 'holding',
                                            'modbus_register_count': '1',
                                            'modbus_mapping_mode': 'single',
                                            'modbus_scale': '1',
                                            'bacnet_enable': '1',
                                            'bacnet_object_type': 'BI',
                                            'bacnet_unit': '95'},
                'alarmUndervoltageCEvent': {'name': 'alarmUndervoltageCEvent',
                                            'json_key': 'alarmUndervoltageCEvent',
                                            'data_type': 'bool',
                                            'unit': 'none',
                                            'readwrite': '0',
                                            'description': 'C-phase undervoltage alarm event',
                                            'modbus_enable': '1',
                                            'modbus_table': 'holding',
                                            'modbus_register_count': '1',
                                            'modbus_mapping_mode': 'single',
                                            'modbus_scale': '1',
                                            'bacnet_enable': '1',
                                            'bacnet_object_type': 'BI',
                                            'bacnet_unit': '95'},
                'alarmShortCircuitEvent': {'name': 'alarmShortCircuitEvent',
                                           'json_key': 'alarmShortCircuitEvent',
                                           'data_type': 'bool',
                                           'unit': 'none',
                                           'readwrite': '0',
                                           'description': 'Short circuit alarm event',
                                           'modbus_enable': '1',
                                           'modbus_table': 'holding',
                                           'modbus_register_count': '1',
                                           'modbus_mapping_mode': 'single',
                                           'modbus_scale': '1',
                                           'bacnet_enable': '1',
                                           'bacnet_object_type': 'BI',
                                           'bacnet_unit': '95'},
                'alarmTempSensor1Event': {'name': 'alarmTempSensor1Event',
                                          'json_key': 'alarmTempSensor1Event',
                                          'data_type': 'bool',
                                          'unit': 'none',
                                          'readwrite': '0',
                                          'description': 'Temperature sensor 1 alarm event',
                                          'modbus_enable': '1',
                                          'modbus_table': 'holding',
                                          'modbus_register_count': '1',
                                          'modbus_mapping_mode': 'single',
                                          'modbus_scale': '1',
                                          'bacnet_enable': '1',
                                          'bacnet_object_type': 'BI',
                                          'bacnet_unit': '95'},
                'alarmTempSensor2Event': {'name': 'alarmTempSensor2Event',
                                          'json_key': 'alarmTempSensor2Event',
                                          'data_type': 'bool',
                                          'unit': 'none',
                                          'readwrite': '0',
                                          'description': 'Temperature sensor 2 alarm event',
                                          'modbus_enable': '1',
                                          'modbus_table': 'holding',
                                          'modbus_register_count': '1',
                                          'modbus_mapping_mode': 'single',
                                          'modbus_scale': '1',
                                          'bacnet_enable': '1',
                                          'bacnet_object_type': 'BI',
                                          'bacnet_unit': '95'},
                'alarmTempSensor3Event': {'name': 'alarmTempSensor3Event',
                                          'json_key': 'alarmTempSensor3Event',
                                          'data_type': 'bool',
                                          'unit': 'none',
                                          'readwrite': '0',
                                          'description': 'Temperature sensor 3 alarm event',
                                          'modbus_enable': '1',
                                          'modbus_table': 'holding',
                                          'modbus_register_count': '1',
                                          'modbus_mapping_mode': 'single',
                                          'modbus_scale': '1',
                                          'bacnet_enable': '1',
                                          'bacnet_object_type': 'BI',
                                          'bacnet_unit': '95'},
                'alarmTempSensor4Event': {'name': 'alarmTempSensor4Event',
                                          'json_key': 'alarmTempSensor4Event',
                                          'data_type': 'bool',
                                          'unit': 'none',
                                          'readwrite': '0',
                                          'description': 'Temperature sensor 4 alarm event',
                                          'modbus_enable': '1',
                                          'modbus_table': 'holding',
                                          'modbus_register_count': '1',
                                          'modbus_mapping_mode': 'single',
                                          'modbus_scale': '1',
                                          'bacnet_enable': '1',
                                          'bacnet_object_type': 'BI',
                                          'bacnet_unit': '95'},
                'alarmLeakageEvent': {'name': 'alarmLeakageEvent',
                                      'json_key': 'alarmLeakageEvent',
                                      'data_type': 'bool',
                                      'unit': 'none',
                                      'readwrite': '0',
                                      'description': 'Leakage current alarm event',
                                      'modbus_enable': '1',
                                      'modbus_table': 'holding',
                                      'modbus_register_count': '1',
                                      'modbus_mapping_mode': 'single',
                                      'modbus_scale': '1',
                                      'bacnet_enable': '1',
                                      'bacnet_object_type': 'BI',
                                      'bacnet_unit': '95'}},
 'sensor_types': {'AN_303_temperature_humidity': {'name': 'AN_303_temperature_humidity',
                                                  'attributes': ['online',
                                                                 'lastOnlineTime',
                                                                 'temperature',
                                                                 'temperatureState',
                                                                 'humidity',
                                                                 'humidityState',
                                                                 'batteryVoltage',
                                                                 'batteryVoltageState',
                                                                 'tamper',
                                                                 'mainVersion',
                                                                 'appVersion',
                                                                 'hardwareVersion',
                                                                 'model',
                                                                 'rssi',
                                                                 'snr'],
                                                  'description': 'Temperature & Humidity sensor',
                                                  'model_name': 'AN-303',
                                                  'version': '20260101',
                                                  'modbus_block_span': '48',
                                                  'bacnet_block_span': '20'},
                  'AN_304_infrared_detector': {'name': 'AN_304_infrared_detector',
                                               'attributes': ['online',
                                                              'lastOnlineTime',
                                                              'batteryVoltage',
                                                              'batteryVoltageState',
                                                              'tamper',
                                                              'tamperEvent',
                                                              'infraredEvent',
                                                              'mainVersion',
                                                              'appVersion',
                                                              'hardwareVersion',
                                                              'model',
                                                              'rssi',
                                                              'snr'],
                                               'description': 'Infrared Detector',
                                               'model_name': 'AN-304',
                                               'version': '20260101',
                                               'modbus_block_span': '48',
                                               'bacnet_block_span': '20'},
                  'JTY_AN_503A_smoke_detector': {'name': 'JTY_AN_503A_smoke_detector',
                                                 'attributes': ['online',
                                                                'lastOnlineTime',
                                                                'temperature',
                                                                'batteryVoltage',
                                                                'batteryVoltageState',
                                                                'tamper',
                                                                'tamperEvent',
                                                                'smokeEvent',
                                                                'smokeStatus',
                                                                'selfCheckEvent',
                                                                'mainVersion',
                                                                'appVersion',
                                                                'hardwareVersion',
                                                                'model',
                                                                'rssi',
                                                                'snr'],
                                                 'description': 'Smoke Detector',
                                                 'model_name': 'JTY-AN-503A',
                                                 'version': '20260101',
                                                 'modbus_block_span': '58',
                                                 'bacnet_block_span': '30'},
                  'CU606_air_quality_sensor': {'name': 'CU606_air_quality_sensor',
                                               'attributes': ['online',
                                                              'lastOnlineTime',
                                                              'temperature',
                                                              'humidity',
                                                              'batteryVoltage',
                                                              'batteryVoltageState',
                                                              'co2',
                                                              'pm25',
                                                              'formaldehyde',
                                                              'tvoc',
                                                              'mainVersion',
                                                              'appVersion',
                                                              'hardwareVersion',
                                                              'model',
                                                              'rssi',
                                                              'snr'],
                                               'description': 'Air Quality Sensor',
                                               'model_name': 'CU606',
                                               'version': '20260101',
                                               'modbus_block_span': '58',
                                               'bacnet_block_span': '20'},
                  'W8004_thermostat': {'name': 'W8004_thermostat',
                                       'attributes': ['online',
                                                      'lastOnlineTime',
                                                      'powerState',
                                                      'setTemperature',
                                                      'workMode',
                                                      'fanSpeed',
                                                      'temperature',
                                                      'humidity',
                                                      'keyLockState',
                                                      'valveState',
                                                      'signalStrength',
                                                      'cumulativeOnTime',
                                                      'cumulativeValveOpenTime',
                                                      'mainVersion',
                                                      'appVersion',
                                                      'hardwareVersion',
                                                      'model',
                                                      'rssi',
                                                      'snr'],
                                       'description': 'Thermostat Controller',
                                       'model_name': 'W8004',
                                       'version': '20260101',
                                       'modbus_block_span': '58',
                                       'bacnet_block_span': '20'},
                  'DS_501_socket': {'name': 'DS_501_socket',
                                    'attributes': ['online',
                                                   'lastOnlineTime',
                                                   'ds501ControlTarget',
                                                   'ds501ControlState',
                                                   'ds501ControlMode',
                                                   'ds501DelaySeconds',
                                                   'ds501ScheduleTimestamp',
                                                   'ds501RepeatDaily',
                                                   'switch',
                                                   'lockState',
                                                   'voltage',
                                                   'current',
                                                   'activePower',
                                                   'energy',
                                                   'timestamp',
                                                   'timerCloseEnabled',
                                                   'timerOpenEnabled',
                                                   'timerLockEnabled',
                                                   'timerUnlockEnabled',
                                                   'mainVersion',
                                                   'appVersion',
                                                   'hardwareVersion',
                                                   'model',
                                                   'rssi',
                                                   'snr'],
                                    'description': 'Smart Socket Panel',
                                    'model_name': 'DS-501',
                                    'version': '20260101',
                                    'modbus_block_span': '68',
                                    'bacnet_block_span': '30'},
                  'EF5600_DN1_electrical_fire_monitor': {'name': 'EF5600_DN1_electrical_fire_monitor',
                                                         'attributes': ['online',
                                                                        'lastOnlineTime',
                                                                        'ef5600CommandCode',
                                                                        'ef5600SettingAddress',
                                                                        'ef5600SettingValueHigh',
                                                                        'ef5600SettingValueLow',
                                                                        'switch',
                                                                        'voltageA',
                                                                        'voltageB',
                                                                        'voltageC',
                                                                        'voltageAvg',
                                                                        'currentA',
                                                                        'currentB',
                                                                        'currentC',
                                                                        'currentAvg',
                                                                        'activePowerA',
                                                                        'activePowerB',
                                                                        'activePowerC',
                                                                        'activePowerTotal',
                                                                        'reactivePowerA',
                                                                        'reactivePowerB',
                                                                        'reactivePowerC',
                                                                        'reactivePowerTotal',
                                                                        'apparentPowerA',
                                                                        'apparentPowerB',
                                                                        'apparentPowerC',
                                                                        'apparentPowerTotal',
                                                                        'powerFactorA',
                                                                        'powerFactorB',
                                                                        'powerFactorC',
                                                                        'powerFactorTotal',
                                                                        'activeEnergy',
                                                                        'reactiveEnergy',
                                                                        'apparentEnergy',
                                                                        'leakageCurrent',
                                                                        'tempSensor1',
                                                                        'tempSensor2',
                                                                        'tempSensor3',
                                                                        'tempSensor4',
                                                                        'tempAvg',
                                                                        'envTemperature',
                                                                        'envHumidity',
                                                                        'electricalAlarm',
                                                                        'electricalAlarmEvent',
                                                                        'alarmOvercurrentA',
                                                                        'alarmOvercurrentB',
                                                                        'alarmOvercurrentC',
                                                                        'alarmOvercurrentAEvent',
                                                                        'alarmOvercurrentBEvent',
                                                                        'alarmOvercurrentCEvent',
                                                                        'alarmOvervoltageA',
                                                                        'alarmOvervoltageB',
                                                                        'alarmOvervoltageC',
                                                                        'alarmOvervoltageAEvent',
                                                                        'alarmOvervoltageBEvent',
                                                                        'alarmOvervoltageCEvent',
                                                                        'alarmUndervoltageA',
                                                                        'alarmUndervoltageB',
                                                                        'alarmUndervoltageC',
                                                                        'alarmUndervoltageAEvent',
                                                                        'alarmUndervoltageBEvent',
                                                                        'alarmUndervoltageCEvent',
                                                                        'alarmShortCircuit',
                                                                        'alarmShortCircuitEvent',
                                                                        'alarmTempSensor1',
                                                                        'alarmTempSensor2',
                                                                        'alarmTempSensor3',
                                                                        'alarmTempSensor4',
                                                                        'alarmTempSensor1Event',
                                                                        'alarmTempSensor2Event',
                                                                        'alarmTempSensor3Event',
                                                                        'alarmTempSensor4Event',
                                                                        'alarmLeakage',
                                                                        'alarmLeakageEvent',
                                                                        'mainVersion',
                                                                        'appVersion',
                                                                        'hardwareVersion',
                                                                        'model',
                                                                        'rssi',
                                                                        'snr'],
                                                         'description': 'Electrical Fire Monitor',
                                                         'model_name': 'EF5600-DN1',
                                                         'version': '20260101',
                                                         'modbus_block_span': '138',
                                                         'bacnet_block_span': '80'},
                  'AN_301_emergency_button': {'name': 'AN_301_emergency_button',
                                              'attributes': ['online',
                                                             'lastOnlineTime',
                                                             'batteryVoltage',
                                                             'tamperStatus',
                                                             'tamperEvent',
                                                             'sosEvent',
                                                             'sosEventTime',
                                                             'mainVersion',
                                                             'appVersion',
                                                             'hardwareVersion',
                                                             'model',
                                                             'rssi',
                                                             'snr'],
                                              'description': 'Emergency Button/SOS Device',
                                              'model_name': 'AN-301',
                                              'version': '20260101',
                                              'modbus_block_span': '48',
                                              'bacnet_block_span': '20'},
                  'undefine': {'name': 'undefine',
                               'attributes': ['online',
                                              'lastOnlineTime',
                                              'lastFport',
                                              'lastPayloadLen',
                                              'lastPayload',
                                              'rssi',
                                              'snr'],
                               'description': 'undefine sensor',
                               'version': '20260101',
                               'modbus_block_span': '145',
                               'bacnet_block_span': '20'},
                  'AN_305_door_contact': {'name': 'AN_305_door_contact',
                                          'attributes': ['online',
                                                         'lastOnlineTime',
                                                         'doorState',
                                                         'batteryVoltage',
                                                         'batteryVoltageState',
                                                         'tamperStatus',
                                                         'batteryLevel',
                                                         'tamperEvent',
                                                         'doorEvent',
                                                         'mainVersion',
                                                         'appVersion',
                                                         'hardwareVersion',
                                                         'model',
                                                         'rssi',
                                                         'snr'],
                                          'description': 'Door Contact Sensor',
                                          'model_name': 'AN-305',
                                          'version': '20260101',
                                          'modbus_block_span': '48',
                                          'bacnet_block_span': '20'},
                  'AN_204_water_leakage': {'name': 'AN_204_water_leakage',
                                           'attributes': ['online',
                                                          'lastOnlineTime',
                                                          'batteryVoltage',
                                                          'waterStatus',
                                                          'waterDuration',
                                                          'batteryLowEvent',
                                                          'waterEvent',
                                                          'mainVersion',
                                                          'appVersion',
                                                          'hardwareVersion',
                                                          'model',
                                                          'rssi',
                                                          'snr'],
                                           'description': 'Water Leakage Sensor',
                                           'model_name': 'AN-204',
                                           'version': '20260101',
                                           'modbus_block_span': '48',
                                           'bacnet_block_span': '20'},
                  'AN_201G_vibrating_wire_strain_gauge': {'name': 'AN_201G_vibrating_wire_strain_gauge',
                                                          'attributes': ['online',
                                                                         'lastOnlineTime',
                                                                         'batteryVoltage',
                                                                         'batteryVoltageState',
                                                                         'timestamp',
                                                                         'vibratingWireSensorModel',
                                                                         'frequency',
                                                                         'frequencyDigit',
                                                                         'temperature',
                                                                         'correctionFactor',
                                                                         'initialFrequency',
                                                                         'initialFrequencyDigit',
                                                                         'initialTemperature',
                                                                         'steelStructureStrain',
                                                                         'concreteStructureStrain',
                                                                         'batteryLowAlarm',
                                                                         'isHeartbeat',
                                                                         'mainVersion',
                                                                         'appVersion',
                                                                         'hardwareVersion',
                                                                         'model',
                                                                         'rssi',
                                                                         'snr'],
                                                          'description': 'Vibrating Wire Strain Gauge',
                                                          'model_name': 'AN-201G',
                                                          'version': '20260101',
                                                          'modbus_block_span': '88',
                                                          'bacnet_block_span': '30'},
                  'AN_113_tilt_angle': {'name': 'AN_113_tilt_angle',
                                        'attributes': ['online',
                                                       'lastOnlineTime',
                                                       'batteryVoltage',
                                                       'batteryVoltageState',
                                                       'tamper',
                                                       'tiltAngle',
                                                       'accelerationAlarm',
                                                       'tiltAlarm',
                                                       'batteryLowEvent',
                                                       'tamperEvent',
                                                       'mainVersion',
                                                       'appVersion',
                                                       'hardwareVersion',
                                                       'model',
                                                       'rssi',
                                                       'snr'],
                                        'description': 'Tilt/Angle Sensor',
                                        'model_name': 'AN-113',
                                        'version': '20260101',
                                        'modbus_block_span': '58',
                                        'bacnet_block_span': '20'},
                  'AN_122_beacon_tracker': {'name': 'AN_122_beacon_tracker',
                                            'attributes': ['online',
                                                           'lastOnlineTime',
                                                           'batteryLevel',
                                                           'tamper',
                                                           'latitude',
                                                           'longitude',
                                                           'positionAccuracy',
                                                           'beaconIdHex',
                                                           'beaconRefRssi',
                                                           'beaconRssi',
                                                           'beaconBatteryLevel',
                                                           'beaconBatteryValid',
                                                           'tiltAngle',
                                                           'batteryLowAlarm',
                                                           'tamperEvent',
                                                           'accelerationAlarm',
                                                           'tiltAlarm',
                                                           'mainVersion',
                                                           'appVersion',
                                                           'hardwareVersion',
                                                           'model',
                                                           'rssi',
                                                           'snr'],
                                            'description': 'Beacon Tracker with GPS',
                                            'model_name': 'AN-122',
                                            'version': '20260101',
                                            'modbus_block_span': '78',
                                            'bacnet_block_span': '30'},
                  'AN_306_radar_presence': {'name': 'AN_306_radar_presence',
                                            'attributes': ['online',
                                                           'lastOnlineTime',
                                                           'presence',
                                                           'tamper',
                                                           'presenceEvent',
                                                           'tamperEvent',
                                                           'isHeartbeat',
                                                           'mainVersion',
                                                           'appVersion',
                                                           'hardwareVersion',
                                                           'model',
                                                           'rssi',
                                                           'snr'],
                                            'description': 'Radar Human Presence Sensor',
                                            'model_name': 'AN-306',
                                            'version': '20260101',
                                            'modbus_block_span': '48',
                                            'bacnet_block_span': '20'},
                  'AN_308_light_illuminance': {'name': 'AN_308_light_illuminance',
                                               'attributes': ['online',
                                                              'lastOnlineTime',
                                                              'batteryVoltage',
                                                              'batteryVoltageState',
                                                              'tamper',
                                                              'illuminance',
                                                              'batteryLowEvent',
                                                              'tamperEvent',
                                                              'mainVersion',
                                                              'appVersion',
                                                              'hardwareVersion',
                                                              'model',
                                                              'rssi',
                                                              'snr'],
                                               'description': 'Light Illuminance Sensor',
                                               'model_name': 'AN-308',
                                               'version': '20260101',
                                               'modbus_block_span': '48',
                                               'bacnet_block_span': '20'},
                  'EX205_liquid_level': {'name': 'EX205_liquid_level',
                                         'attributes': ['online',
                                                        'lastOnlineTime',
                                                        'batteryVoltage',
                                                        'batteryVoltageState',
                                                        'distance',
                                                        'liquidLevel',
                                                        'liquidLevelPercent',
                                                        'liquidLevelStatus',
                                                        'liquidLevelEvent',
                                                        'batteryLowEvent',
                                                        'sensorAbnormal',
                                                        'mainVersion',
                                                        'appVersion',
                                                        'hardwareVersion',
                                                        'model',
                                                        'rssi',
                                                        'snr'],
                                         'description': 'Radar Liquid Level Meter',
                                         'model_name': 'EX205',
                                         'version': '20260101',
                                         'modbus_block_span': '58',
                                         'bacnet_block_span': '20'},
                  'AN_307_sound_light_alarm': {'name': 'AN_307_sound_light_alarm',
                                               'attributes': ['online',
                                                              'lastOnlineTime',
                                                              'alarmStatus',
                                                              'alarmDurationSeconds',
                                                              'mainVersion',
                                                              'appVersion',
                                                              'hardwareVersion',
                                                              'model',
                                                              'rssi',
                                                              'snr'],
                                               'description': 'Sound & Light Alarm',
                                               'model_name': 'AN-307',
                                               'version': '20260101',
                                               'modbus_block_span': '48',
                                               'bacnet_block_span': '20'},
                  'DS_103_3ch_switch': {'name': 'DS_103_3ch_switch',
                                        'attributes': ['online',
                                                       'lastOnlineTime',
                                                       'ds103ControlTarget',
                                                       'ds103ControlState',
                                                       'ds103ControlMode',
                                                       'ds103DelaySeconds',
                                                       'ds103ScheduleTimestamp',
                                                       'ds103RepeatDaily',
                                                       'lockState',
                                                       'switch1State',
                                                       'switch2State',
                                                       'switch3State',
                                                       'timestamp',
                                                       'switchTimerStatus',
                                                       'timerCloseEnabled1',
                                                       'timerOpenEnabled1',
                                                       'timerCloseEnabled2',
                                                       'timerOpenEnabled2',
                                                       'timerCloseEnabled3',
                                                       'timerOpenEnabled3',
                                                       'timerLockEnabled',
                                                       'timerUnlockEnabled',
                                                       'mainVersion',
                                                       'appVersion',
                                                       'hardwareVersion',
                                                       'model',
                                                       'rssi',
                                                       'snr'],
                                        'description': '3-Channel Switch Controller',
                                        'model_name': 'DS-103',
                                        'version': '20260101',
                                        'modbus_block_span': '68',
                                        'bacnet_block_span': '30'},
                  'EX301_vibration': {'name': 'EX301_vibration',
                                      'attributes': ['online',
                                                     'lastOnlineTime',
                                                     'batteryVoltage',
                                                     'batteryVoltageState',
                                                     'temperature',
                                                     'temperatureAlarmStatus',
                                                     'vibFreqX',
                                                     'vibFreqY',
                                                     'vibFreqZ',
                                                     'vibAccelX',
                                                     'vibAccelY',
                                                     'vibAccelZ',
                                                     'vibVelX',
                                                     'vibVelY',
                                                     'vibVelZ',
                                                     'vibDispX',
                                                     'vibDispY',
                                                     'vibDispZ',
                                                     'vibrationAlarmStatus',
                                                     'alarmAccelX',
                                                     'alarmAccelY',
                                                     'alarmAccelZ',
                                                     'alarmVelX',
                                                     'alarmVelY',
                                                     'alarmVelZ',
                                                     'alarmDispX',
                                                     'alarmDispY',
                                                     'alarmDispZ',
                                                     'sensorAbnormal',
                                                     'batteryLowEvent',
                                                     'vibrationAlarmEvent',
                                                     'alarmEventActive',
                                                     'mainVersion',
                                                     'appVersion',
                                                     'hardwareVersion',
                                                     'model',
                                                     'rssi',
                                                     'snr'],
                                      'description': 'Vibration Sensor',
                                      'model_name': 'EX301',
                                      'version': '20260101',
                                      'modbus_block_span': '78',
                                      'bacnet_block_span': '50'},
                  'CM100_beacon_receiver': {'name': 'CM100_beacon_receiver',
                                            'attributes': ['online',
                                                           'lastOnlineTime',
                                                           'batteryLevel',
                                                           'beaconIdHex',
                                                           'beaconRssi',
                                                           'beaconBatteryLevel',
                                                           'beaconBatteryValid',
                                                           'batteryLowAlarm',
                                                           'sosEvent',
                                                           'isHeartbeat',
                                                           'mainVersion',
                                                           'appVersion',
                                                           'hardwareVersion',
                                                           'model',
                                                           'rssi',
                                                           'snr'],
                                            'description': 'Beacon Receiver/Gateway',
                                            'model_name': 'CM100',
                                            'version': '20260101',
                                            'modbus_block_span': '68',
                                            'bacnet_block_span': '20'},
                  'GB100_safety_helmet': {'name': 'GB100_safety_helmet',
                                          'attributes': ['online',
                                                         'lastOnlineTime',
                                                         'batteryLevel',
                                                         'atmosphericPressure',
                                                         'altitude',
                                                         'temperature',
                                                         'temperatureAlarmStatus',
                                                         'fallAlarmStatus',
                                                         'fallAlarmEvent',
                                                         'helmetRemovalAlarmStatus',
                                                         'helmetRemovalAlarmEvent',
                                                         'electricityProximityAlarmStatus',
                                                         'electricityProximityAlarmEvent',
                                                         'impactAlarmStatus',
                                                         'impactAlarmEvent',
                                                         'silenceAlarmStatus',
                                                         'silenceAlarmEvent',
                                                         'heightAccessAlarmStatus',
                                                         'heightAccessAlarmEvent',
                                                         'latitude',
                                                         'longitude',
                                                         'positionAccuracy',
                                                         'gpsAbsoluteTimestamp',
                                                         'gpsTimeValid',
                                                         'beaconIdHex',
                                                         'beaconRssi',
                                                         'beaconBatteryLevel',
                                                         'beaconBatteryValid',
                                                         'batteryLowAlarm',
                                                         'temperatureEvent',
                                                         'sosEvent',
                                                         'safetyAlarmActive',
                                                         'isHeartbeat',
                                                         'mainVersion',
                                                         'appVersion',
                                                         'hardwareVersion',
                                                         'model',
                                                         'rssi',
                                                         'snr'],
                                          'description': 'Safety Helmet with Multiple Sensors',
                                          'model_name': 'GB100',
                                          'version': '20260101',
                                          'modbus_block_span': '98',
                                          'bacnet_block_span': '40'}}}

CONFIG_SNAPSHOT_PATH = Path(__file__).with_name("openwrt的配置文件iot_hub")
MODBUS_DEVICE_META_HEADER_REG_COUNT = 6
MODBUS_DEVICE_META_LAYOUT_HASH_OFFSET = 0
MODBUS_DEVICE_META_LAYOUT_HASH_REG_COUNT = 4
MODBUS_DEVICE_META_PROFILE_VERSION_OFFSET = 4
MODBUS_DEVICE_META_PROFILE_VERSION_REG_COUNT = 2  # uint32 big-endian: high word + low word
SUPPORTED_SENSOR_MODELS = {
    "W8004": W8004_SENSOR_TYPE,
    "AN-201G": AN201G_SENSOR_TYPE,
    "AN-307": AN307_SENSOR_TYPE,
    "DS-501": DS501_SENSOR_TYPE,
    "DS-103": DS103_SENSOR_TYPE,
    "EF5600-DN1": EF5600_SENSOR_TYPE,
}
READ_ONLY_SENSOR_TYPES = {AN201G_SENSOR_TYPE}
DEFAULT_MODBUS_PORT = 8234
DEFAULT_MODBUS_SLAVE_ID = 2
DEFAULT_MAX_RETRIES = 3
DEFAULT_CONFIRM_WINDOW_SECONDS = 15.0
DEFAULT_CONFIRM_POLL_SECONDS = 0.2
DEFAULT_POWER_VALUE = True
DEFAULT_LOCK_VALUE = True
DEFAULT_SET_TEMPERATURE = 23.0
DEFAULT_WORK_MODE = 1
DEFAULT_FAN_SPEED = 1
DEFAULT_ALARM_VALUE = True
DEFAULT_ALARM_DURATION_SECONDS = 5
DEFAULT_DS103_SWITCH_TARGET = "1"
DEFAULT_DS103_REPEAT_DAILY = False

HELP_EXAMPLES = """Examples:
    python modbus_tcp_write.py --ip 192.168.1.10 --sensorType DS-501 switchDelay --value 1 --delaySeconds 30
    python modbus_tcp_write.py --ip 192.168.1.10 --sensorType DS-103 cancelSwitchTimer --channel 2
    python modbus_tcp_write.py --ip 192.168.1.10 --sensorType EF5600-DN1 selfTest
    python modbus_tcp_write.py --ip 192.168.1.10 --sensorType EF5600-DN1 setOvercurrent --percent 120 --delaySeconds 5
"""

EF5600_ACTION_RESET = 0x01
EF5600_ACTION_SELF_TEST = 0x02
EF5600_ACTION_SILENCE = 0x03
EF5600_ACTION_BREAKER_OPEN = 0x04
EF5600_ACTION_BREAKER_CLOSE = 0x05
EF5600_ACTION_QUERY_SETTING = 0x06
EF5600_ACTION_SET_SETTING = 0x07

EF5600_CURRENT_RATIO_ADDRESS = 0x1001
EF5600_OVERCURRENT_ADDRESS = 0x1002
EF5600_OVERVOLTAGE_ADDRESS = 0x1003
EF5600_UNDERVOLTAGE_ADDRESS = 0x1004
EF5600_OVERTEMPERATURE_ADDRESS = 0x1005
EF5600_TEMP_HUMIDITY_ADDRESS = 0x1006
EF5600_LEAKAGE_ADDRESS = 0x1007

W8004_LAYOUT = [
    {"name": "powerState", "offset": 3, "register_count": 1, "value_type": "bool", "display_precision": 0},
    {"name": "setTemperature", "offset": 4, "register_count": 1, "value_type": "float", "scale": 100.0, "display_precision": 1},
    {"name": "workMode", "offset": 5, "register_count": 1, "value_type": "int", "display_precision": 0},
    {"name": "fanSpeed", "offset": 6, "register_count": 1, "value_type": "int", "display_precision": 0},
    {"name": "keyLockState", "offset": 9, "register_count": 1, "value_type": "bool", "display_precision": 0},
]

AN307_LAYOUT = [
    {"name": "alarmStatus", "offset": 3, "register_count": 1, "value_type": "bool", "display_precision": 0},
    {"name": "alarmDurationSeconds", "offset": 4, "register_count": 1, "value_type": "int", "display_precision": 0, "confirm_required": False},
]

DS501_LAYOUT = [
    {"name": "switch", "offset": 11, "register_count": 1, "value_type": "bool", "display_precision": 0},
    {"name": "lockState", "offset": 12, "register_count": 1, "value_type": "bool", "display_precision": 0},
    {"name": "ds501ControlTarget", "offset": 3, "register_count": 1, "value_type": "int", "display_precision": 0, "confirm_required": False},
    {"name": "ds501ControlState", "offset": 4, "register_count": 1, "value_type": "bool", "display_precision": 0, "confirm_required": False},
    {"name": "ds501ControlMode", "offset": 5, "register_count": 1, "value_type": "int", "display_precision": 0, "confirm_required": False},
    {"name": "ds501DelaySeconds", "offset": 6, "register_count": 2, "value_type": "int", "display_precision": 0, "mapping_mode": "big_endian", "confirm_required": False},
    {"name": "ds501ScheduleTimestamp", "offset": 8, "register_count": 2, "value_type": "int", "display_precision": 0, "mapping_mode": "big_endian", "confirm_required": False},
    {"name": "ds501RepeatDaily", "offset": 10, "register_count": 1, "value_type": "bool", "display_precision": 0, "confirm_required": False},
]

DS103_LAYOUT = [
    {"name": "lockState", "offset": 11, "register_count": 1, "value_type": "bool", "display_precision": 0},
    {"name": "switch1State", "offset": 12, "register_count": 1, "value_type": "bool", "display_precision": 0},
    {"name": "switch2State", "offset": 13, "register_count": 1, "value_type": "bool", "display_precision": 0},
    {"name": "switch3State", "offset": 14, "register_count": 1, "value_type": "bool", "display_precision": 0},
    {"name": "ds103ControlTarget", "offset": 3, "register_count": 1, "value_type": "int", "display_precision": 0, "confirm_required": False},
    {"name": "ds103ControlState", "offset": 4, "register_count": 1, "value_type": "bool", "display_precision": 0, "confirm_required": False},
    {"name": "ds103ControlMode", "offset": 5, "register_count": 1, "value_type": "int", "display_precision": 0, "confirm_required": False},
    {"name": "ds103DelaySeconds", "offset": 6, "register_count": 2, "value_type": "int", "display_precision": 0, "mapping_mode": "big_endian", "confirm_required": False},
    {"name": "ds103ScheduleTimestamp", "offset": 8, "register_count": 2, "value_type": "int", "display_precision": 0, "mapping_mode": "big_endian", "confirm_required": False},
    {"name": "ds103RepeatDaily", "offset": 10, "register_count": 1, "value_type": "bool", "display_precision": 0, "confirm_required": False},
]

EF5600_LAYOUT = [
    {"name": "ef5600CommandCode", "offset": 3, "register_count": 1, "value_type": "int", "display_precision": 0, "confirm_required": False},
    {"name": "ef5600SettingAddress", "offset": 4, "register_count": 1, "value_type": "int", "display_precision": 0, "confirm_required": False},
    {"name": "ef5600SettingValueHigh", "offset": 5, "register_count": 1, "value_type": "int", "display_precision": 0, "confirm_required": False},
    {"name": "ef5600SettingValueLow", "offset": 6, "register_count": 1, "value_type": "int", "display_precision": 0, "confirm_required": False},
    {"name": "switch", "offset": 7, "register_count": 1, "value_type": "bool", "display_precision": 0},
]

DEVICE_SPECS = {
    W8004_SENSOR_TYPE: {
        "label": W8004_SENSOR_TYPE,
        "layout": W8004_LAYOUT,
        "modes": {"power", "climate", "lock"},
    },
    AN307_SENSOR_TYPE: {
        "label": AN307_SENSOR_TYPE,
        "layout": AN307_LAYOUT,
        "modes": {"alarm"},
    },
    DS501_SENSOR_TYPE: {
        "label": DS501_SENSOR_TYPE,
        "layout": DS501_LAYOUT,
        "modes": {"switch", "lock", "switchDelay", "switchSchedule", "lockDelay", "lockSchedule", "cancelSwitchTimer", "cancelLockTimer", "query"},
    },
    DS103_SENSOR_TYPE: {
        "label": DS103_SENSOR_TYPE,
        "layout": DS103_LAYOUT,
        "modes": {"switch", "lock", "switchDelay", "switchSchedule", "lockDelay", "lockSchedule", "cancelSwitchTimer", "cancelLockTimer", "query"},
    },
    EF5600_SENSOR_TYPE: {
        "label": EF5600_SENSOR_TYPE,
        "layout": EF5600_LAYOUT,
        "modes": {
            "reset",
            "selfTest",
            "silence",
            "breakerOpen",
            "breakerClose",
            "queryCurrentRatio",
            "setCurrentRatio",
            "queryOvercurrent",
            "setOvercurrent",
            "queryOvervoltage",
            "setOvervoltage",
            "queryUndervoltage",
            "setUndervoltage",
            "queryOvertemperature",
            "setOvertemperature",
            "queryTempHumidity",
            "setTempHumidity",
            "queryLeakage",
            "setLeakage",
        },
    },
}


def strip_uci_inline_comment(text):
    in_quote = False
    result = []
    for char in str(text):
        if char == "'":
            in_quote = not in_quote
        if char == "#" and not in_quote:
            break
        result.append(char)
    return "".join(result).strip()


def parse_uci_scalar(text):
    value = strip_uci_inline_comment(text)
    if len(value) >= 2 and value[0] == "'" and value[-1] == "'":
        return value[1:-1]
    return value


def load_uci_snapshot(path=CONFIG_SNAPSHOT_PATH):
    if not path.exists():
        return _BUILTIN_SNAPSHOT

    snapshot = {"globals": {}, "attributes": {}, "sensor_types": {}}
    current_kind = None
    current_entry = None

    for raw_line in path.read_text(encoding="utf-8").splitlines():
        line = raw_line.strip()
        if not line or line.startswith("#"):
            continue

        if line.startswith("config "):
            parts = line.split(None, 2)
            current_kind = parts[1] if len(parts) > 1 else None
            current_name = parse_uci_scalar(parts[2]) if len(parts) > 2 else None
            if current_kind == "global":
                current_entry = snapshot["globals"]
            elif current_kind == "attribute" and current_name:
                current_entry = {"name": current_name}
                snapshot["attributes"][current_name] = current_entry
            elif current_kind == "sensor_type" and current_name:
                current_entry = {"name": current_name, "attributes": []}
                snapshot["sensor_types"][current_name] = current_entry
            else:
                current_entry = None
            continue

        if current_entry is None:
            continue

        if line.startswith("option "):
            _, key, value = line.split(None, 2)
            current_entry[key] = parse_uci_scalar(value)
            continue

        if line.startswith("list ") and current_kind == "sensor_type":
            _, key, value = line.split(None, 2)
            if key == "attributes":
                current_entry.setdefault("attributes", []).append(parse_uci_scalar(value))

    return snapshot


UCI_SNAPSHOT = load_uci_snapshot()


def resolve_sensor_type_name(snapshot, sensor_type_or_model, default_sensor_type=None):
    if not sensor_type_or_model:
        return default_sensor_type

    sensor_types = snapshot.get("sensor_types", {}) if snapshot else {}
    requested = str(sensor_type_or_model).strip().casefold()
    for sensor_type_name, sensor in sensor_types.items():
        if str(sensor.get("model_name", "")).strip().casefold() == requested:
            return sensor_type_name

    return SUPPORTED_SENSOR_MODELS.get(str(sensor_type_or_model).strip())


def get_sensor_display_name(snapshot, sensor_type_name):
    sensor = snapshot.get("sensor_types", {}).get(sensor_type_name, {}) if snapshot else {}
    model_name = str(sensor.get("model_name", "")).strip()
    return model_name or sensor_type_name


def get_sensor_profile_version(snapshot, sensor_type_name):
    sensor = snapshot.get("sensor_types", {}).get(sensor_type_name, {}) if snapshot else {}
    raw = str(sensor.get("version", "0")).strip()
    return int(raw) if raw.isdigit() else 0


def value_kind_from_entry(entry, attribute=None):
    if attribute:
        data_type = str(attribute.get("data_type", "")).strip().lower()
        if data_type in {"bool", "float", "string", "binary"}:
            return data_type
        if data_type in {"int", "uint", "timestamp"}:
            return "int"

    value_type = str(entry.get("value_type", "")).strip().lower()
    if value_type in {"bool", "float", "string", "binary"}:
        return value_type
    if value_type:
        return "int"
    return "unknown"


def normalize_hash_scale(value):
    try:
        return format(float(value), ".9g")
    except (TypeError, ValueError):
        return "1"


def fnv1a32_update(hash_value, token):
    data = str(token or "").encode("utf-8") + b"\x1f"
    for byte in data:
        hash_value ^= byte
        hash_value = (hash_value * 16777619) & 0xFFFFFFFF
    return hash_value


def compute_modbus_layout_hash(layout, snapshot=UCI_SNAPSHOT, sensor_type=None):
    """Hash all Modbus holding-register fields by (name, json_key, kind, table, register_count,
    mapping_mode, scale) in field order.  Absolute offset is intentionally excluded — it is
    determined by field sequence + register_count values, so any reorder, insertion, or
    deletion is still detected. Also catches name and type changes in any field."""
    hash_value = 2166136261
    hash_value = fnv1a32_update(hash_value, "modbus")

    if snapshot and sensor_type:
        sensor = snapshot.get("sensor_types", {}).get(sensor_type)
        attributes_map = snapshot.get("attributes", {})
        if sensor:
            for attribute_name in sensor.get("attributes", []):
                attribute = attributes_map.get(attribute_name, {})
                if attribute.get("modbus_enable") != "1" or attribute.get("modbus_table", "holding") != "holding":
                    continue
                try:
                    reg_count = int(attribute.get("modbus_register_count", 1) or 1)
                except (ValueError, TypeError):
                    reg_count = 1
                hash_value = fnv1a32_update(hash_value, attribute_name)
                hash_value = fnv1a32_update(hash_value, attribute.get("json_key", attribute_name))
                hash_value = fnv1a32_update(hash_value, value_kind_from_entry({"value_type": None}, attribute))
                hash_value = fnv1a32_update(hash_value, attribute.get("modbus_table", "holding"))
                hash_value = fnv1a32_update(hash_value, reg_count)
                hash_value = fnv1a32_update(hash_value, attribute.get("modbus_mapping_mode", "single"))
                hash_value = fnv1a32_update(hash_value, normalize_hash_scale(float(attribute.get("modbus_scale", 1.0) or 1.0)))
            return f"{hash_value:08X}"

    # Fallback: hash the provided control-field layout entries
    attributes = snapshot.get("attributes", {}) if snapshot else {}
    for entry in layout:
        attribute = attributes.get(entry.get("name", ""), {}) if attributes else {}
        hash_value = fnv1a32_update(hash_value, entry.get("name", ""))
        hash_value = fnv1a32_update(hash_value, entry.get("json_key", entry.get("name", "")))
        hash_value = fnv1a32_update(hash_value, value_kind_from_entry(entry, attribute))
        hash_value = fnv1a32_update(hash_value, attribute.get("modbus_table", "holding") or "holding")
        hash_value = fnv1a32_update(hash_value, entry.get("register_count", 1))
        hash_value = fnv1a32_update(hash_value, entry.get("mapping_mode", "single"))
        hash_value = fnv1a32_update(hash_value, normalize_hash_scale(entry.get("scale", 1.0)))
    return f"{hash_value:08X}"


def get_snapshot_global_int(snapshot, key, default_value):
    if not snapshot:
        return default_value
    raw_value = snapshot.get("globals", {}).get(key)
    try:
        return int(raw_value)
    except (TypeError, ValueError):
        return default_value


def infer_value_type(attribute, fallback_entry):
    if fallback_entry.get("value_type"):
        return fallback_entry["value_type"]
    data_type = str(attribute.get("data_type", "")).lower()
    if data_type == "bool":
        return "bool"
    if data_type == "float":
        return "float"
    return "int"


def shift_modbus_layout_after_meta_header(layout):
    shifted = []
    for entry in layout:
        copied = dict(entry)
        copied["offset"] = int(copied.get("offset", 0)) + MODBUS_DEVICE_META_HEADER_REG_COUNT
        shifted.append(copied)
    return shifted


def build_modbus_layout_from_snapshot(sensor_type, fallback_layout, snapshot=UCI_SNAPSHOT):
    if not snapshot:
        return shift_modbus_layout_after_meta_header(fallback_layout)

    sensor = snapshot.get("sensor_types", {}).get(sensor_type)
    if not sensor:
        return shift_modbus_layout_after_meta_header(fallback_layout)

    fallback_by_name = {entry["name"]: entry for entry in fallback_layout}
    built_by_name = {}
    offset = MODBUS_DEVICE_META_HEADER_REG_COUNT

    for attribute_name in sensor.get("attributes", []):
        attribute = snapshot.get("attributes", {}).get(attribute_name)
        if not attribute:
            continue
        if attribute.get("modbus_enable") != "1" or attribute.get("modbus_table") != "holding":
            continue

        try:
            register_count = int(attribute.get("modbus_register_count", "1") or 1)
        except ValueError:
            register_count = 1

        fallback_entry = fallback_by_name.get(attribute_name)
        if fallback_entry:
            merged_entry = dict(fallback_entry)
            merged_entry["offset"] = offset
            merged_entry["register_count"] = register_count
            merged_entry["mapping_mode"] = attribute.get("modbus_mapping_mode") or merged_entry.get("mapping_mode", "single")
            try:
                merged_entry["scale"] = float(attribute.get("modbus_scale", merged_entry.get("scale", 1.0)) or 1.0)
            except ValueError:
                merged_entry["scale"] = float(merged_entry.get("scale", 1.0) or 1.0)
            merged_entry["value_type"] = infer_value_type(attribute, merged_entry)
            built_by_name[attribute_name] = merged_entry

        offset += register_count

    if any(entry["name"] not in built_by_name for entry in fallback_layout):
        return shift_modbus_layout_after_meta_header(fallback_layout)

    return [built_by_name[entry["name"]] for entry in fallback_layout]


def entry_scale(entry):
    return float(entry.get("scale", 1.0) or 1.0)


def coerce_cli_value(raw_value, entry):
    value_type = entry.get("value_type")
    text = str(raw_value).strip()
    if value_type == "bool":
        return text.lower() in {"1", "true", "on", "yes"}
    if value_type == "float":
        return float(text)
    return int(float(text))


def encode_modbus_value(value, entry):
    value_type = entry.get("value_type")
    if value_type == "bool":
        return [1 if value else 0]
    if int(entry.get("register_count", 1)) == 2:
        raw_value = int(value) & 0xFFFFFFFF
        if entry.get("mapping_mode") == "little_endian":
            return [raw_value & 0xFFFF, (raw_value >> 16) & 0xFFFF]
        return [(raw_value >> 16) & 0xFFFF, raw_value & 0xFFFF]
    if value_type == "float":
        scaled = int(round(float(value) * entry_scale(entry)))
        return [scaled & 0xFFFF]
    return [int(value) & 0xFFFF]


def decode_modbus_registers(registers, entry):
    if not registers:
        return None
    if len(registers) == 2:
        if entry.get("mapping_mode") == "little_endian":
            return (int(registers[1]) << 16) | int(registers[0])
        return (int(registers[0]) << 16) | int(registers[1])
    raw_value = int(registers[0])
    value_type = entry.get("value_type")
    if value_type == "bool":
        return raw_value != 0
    if value_type == "float":
        return raw_value / entry_scale(entry)
    return raw_value


def values_match(expected, observed, entry):
    if observed is None:
        return False
    value_type = entry.get("value_type")
    if value_type == "float":
        tolerance = 0.5 / entry_scale(entry)
        return abs(float(expected) - float(observed)) <= tolerance
    return expected == observed


def format_value(value, entry):
    if value is None:
        return "<unavailable>"
    if entry.get("value_type") == "float":
        precision = int(entry.get("display_precision", 1))
        return f"{float(value):.{precision}f}"
    if entry.get("value_type") == "bool":
        return "1" if value else "0"
    return str(value)


def to_signed_16bit(value):
    word = int(value) & 0xFFFF
    return word - 0x10000 if word >= 0x8000 else word


def format_holding_register_reference(offset):
    return f"{offset} (4x{40001 + int(offset)})"


def describe_modbus_batches(write_batches):
    print("Modbus Poll write guide:")
    for batch_index, batch in enumerate(write_batches, start=1):
        function_code = "FC06 Write Single Register" if len(batch["values"]) == 1 else "FC16 Write Multiple Registers"
        print(
            f"  Batch {batch_index}: {function_code} | Start register: {format_holding_register_reference(batch['offset'])} | Count: {len(batch['values'])}"
        )
        for item in batch["items"]:
            for register_index, register_value in enumerate(item["values"]):
                register_offset = item["offset"] + register_index
                print(
                    "    "
                    f"{item['name']} -> register {format_holding_register_reference(register_offset)} "
                    f"raw={int(register_value) & 0xFFFF} signed={to_signed_16bit(register_value)}"
                )


def read_holding_registers_compat(client, offset, count, slave_id):
    try:
        return client.read_holding_registers(offset, count=count, device_id=slave_id)
    except TypeError:
        pass

    try:
        return client.read_holding_registers(offset, count=count, slave=slave_id)
    except TypeError:
        pass

    try:
        return client.read_holding_registers(offset, count=count, unit=slave_id)
    except TypeError:
        pass

    try:
        return client.read_holding_registers(offset, count, slave=slave_id)
    except TypeError:
        pass

    try:
        return client.read_holding_registers(offset, count, unit=slave_id)
    except TypeError:
        pass

    raise RuntimeError("unable to find a compatible pymodbus read_holding_registers API")


def decode_string_registers(registers):
    chars = []
    for value in registers or []:
        chars.append(chr((int(value) >> 8) & 0xFF))
        chars.append(chr(int(value) & 0xFF))
    return "".join(chars).split("\x00", 1)[0].strip()


def read_remote_protocol_header(client, slave_id):
    response = read_holding_registers_compat(
        client,
        0,
        MODBUS_DEVICE_META_HEADER_REG_COUNT,
        slave_id,
    )
    if response.isError():
        return None
    registers = response.registers or []
    if len(registers) < MODBUS_DEVICE_META_HEADER_REG_COUNT:
        return None
    return {
        "layoutHash": decode_string_registers(registers[MODBUS_DEVICE_META_LAYOUT_HASH_OFFSET:MODBUS_DEVICE_META_LAYOUT_HASH_OFFSET + MODBUS_DEVICE_META_LAYOUT_HASH_REG_COUNT]),
        "profileVersion": (int(registers[MODBUS_DEVICE_META_PROFILE_VERSION_OFFSET]) << 16) | int(registers[MODBUS_DEVICE_META_PROFILE_VERSION_OFFSET + 1]),
    }


def write_registers_compat(client, offset, values, slave_id):
    if len(values) == 1:
        value = values[0]
        for kwargs in ({"device_id": slave_id}, {"slave": slave_id}, {"unit": slave_id}, {}):
            try:
                return client.write_register(offset, value, **kwargs)
            except TypeError:
                continue
    else:
        for kwargs in ({"device_id": slave_id}, {"slave": slave_id}, {"unit": slave_id}, {}):
            try:
                return client.write_registers(offset, values, **kwargs)
            except TypeError:
                continue
    raise RuntimeError("unable to find a compatible pymodbus write_register API")


def build_write_batches(expected, entries_by_name):
    ordered_targets = []
    for attribute_name, desired_value in expected.items():
        entry = entries_by_name[attribute_name]
        ordered_targets.append(
            {
                "name": attribute_name,
                "offset": int(entry["offset"]),
                "values": encode_modbus_value(desired_value, entry),
                "entry": entry,
            }
        )

    ordered_targets.sort(key=lambda item: item["offset"])

    batches = []
    current_batch = None

    for target in ordered_targets:
        if current_batch is None:
            current_batch = {
                "offset": target["offset"],
                "values": list(target["values"]),
                "names": [target["name"]],
                "items": [target],
            }
            continue

        next_offset = current_batch["offset"] + len(current_batch["values"])
        if target["offset"] == next_offset:
            current_batch["values"].extend(target["values"])
            current_batch["names"].append(target["name"])
            current_batch["items"].append(target)
            continue

        batches.append(current_batch)
        current_batch = {
            "offset": target["offset"],
            "values": list(target["values"]),
            "names": [target["name"]],
            "items": [target],
        }

    if current_batch is not None:
        batches.append(current_batch)

    return batches


def parse_ds103_switch_target(raw_value):
    text = str(raw_value).strip().lower()
    aliases = {
        "1": 1,
        "left": 1,
        "2": 2,
        "middle": 2,
        "mid": 2,
        "center": 2,
        "3": 3,
        "right": 3,
        "all": 255,
        "ff": 255,
        "255": 255,
    }
    if text not in aliases:
        raise ValueError(f"Unsupported DS-103 switch target: {raw_value}")
    return aliases[text]


def build_ds103_switch_confirmation(target, desired_state):
    if target == 255:
        return {
            "switch1State": desired_state,
            "switch2State": desired_state,
            "switch3State": desired_state,
        }
    return {f"switch{target}State": desired_state}


def build_ds103_control_block(target, state=0, mode=0, delay_seconds=0, schedule_timestamp=0, repeat_daily=False):
    return {
        "ds103ControlTarget": int(target),
        "ds103ControlState": bool(state),
        "ds103ControlMode": int(mode),
        "ds103DelaySeconds": int(delay_seconds),
        "ds103ScheduleTimestamp": int(schedule_timestamp),
        "ds103RepeatDaily": bool(repeat_daily),
    }


def build_ds501_control_block(target, state=0, mode=0, delay_seconds=0, schedule_timestamp=0, repeat_daily=False):
    return {
        "ds501ControlTarget": int(target),
        "ds501ControlState": bool(state),
        "ds501ControlMode": int(mode),
        "ds501DelaySeconds": int(delay_seconds),
        "ds501ScheduleTimestamp": int(schedule_timestamp),
        "ds501RepeatDaily": bool(repeat_daily),
    }


def require_uint8(raw_value, label):
    numeric = int(raw_value)
    if numeric < 0 or numeric > 0xFF:
        raise ValueError(f"{label} must be between 0 and 255")
    return numeric


def split_uint16(raw_value, label):
    numeric = int(raw_value)
    if numeric < 0 or numeric > 0xFFFF:
        raise ValueError(f"{label} must be between 0 and 65535")
    return (numeric >> 8) & 0xFF, numeric & 0xFF


def build_ef5600_control_block(command_code, setting_address=0, value_high=0, value_low=0):
    return {
        "ef5600CommandCode": int(command_code),
        "ef5600SettingAddress": int(setting_address),
        "ef5600SettingValueHigh": int(value_high),
        "ef5600SettingValueLow": int(value_low),
    }


def build_control_plan(args, entries_by_name, sensor_type):
    if args.mode == "alarm":
        target = {"alarmStatus": coerce_cli_value(args.value, entries_by_name["alarmStatus"])}
        if target["alarmStatus"] and args.durationSeconds is not None:
            target["alarmDurationSeconds"] = coerce_cli_value(args.durationSeconds, entries_by_name["alarmDurationSeconds"])
        return target, {"alarmStatus": target["alarmStatus"]}
    if sensor_type == DS501_SENSOR_TYPE:
        if args.mode == "switch":
            desired_state = coerce_cli_value(args.value, entries_by_name["switch"])
            return build_ds501_control_block(1, desired_state, mode=0), {"switch": desired_state}
        if args.mode == "lock":
            desired_state = coerce_cli_value(args.value, entries_by_name["lockState"])
            return build_ds501_control_block(254, desired_state, mode=0), {"lockState": desired_state}
        if args.mode == "switchDelay":
            desired_state = coerce_cli_value(args.value, entries_by_name["switch"])
            return build_ds501_control_block(1, desired_state, mode=1, delay_seconds=args.delaySeconds), {}
        if args.mode == "switchSchedule":
            desired_state = coerce_cli_value(args.value, entries_by_name["switch"])
            return build_ds501_control_block(1, desired_state, mode=2, schedule_timestamp=args.scheduleTimestamp, repeat_daily=args.repeatDaily), {}
        if args.mode == "lockDelay":
            desired_state = coerce_cli_value(args.value, entries_by_name["lockState"])
            return build_ds501_control_block(254, desired_state, mode=1, delay_seconds=args.delaySeconds), {}
        if args.mode == "lockSchedule":
            desired_state = coerce_cli_value(args.value, entries_by_name["lockState"])
            return build_ds501_control_block(254, desired_state, mode=2, schedule_timestamp=args.scheduleTimestamp, repeat_daily=args.repeatDaily), {}
        if args.mode == "cancelSwitchTimer":
            return build_ds501_control_block(1, 0, mode=3), {}
        if args.mode == "cancelLockTimer":
            return build_ds501_control_block(254, 0, mode=3), {}
        if args.mode == "query":
            return build_ds501_control_block(255, 0, mode=4), {}
    if sensor_type == EF5600_SENSOR_TYPE:
        if args.mode == "reset":
            return build_ef5600_control_block(EF5600_ACTION_RESET), {}
        if args.mode == "selfTest":
            return build_ef5600_control_block(EF5600_ACTION_SELF_TEST), {}
        if args.mode == "silence":
            return build_ef5600_control_block(EF5600_ACTION_SILENCE), {}
        if args.mode == "breakerOpen":
            return build_ef5600_control_block(EF5600_ACTION_BREAKER_OPEN), {"switch": False}
        if args.mode == "breakerClose":
            return build_ef5600_control_block(EF5600_ACTION_BREAKER_CLOSE), {"switch": True}
        if args.mode == "queryCurrentRatio":
            return build_ef5600_control_block(EF5600_ACTION_QUERY_SETTING, EF5600_CURRENT_RATIO_ADDRESS), {}
        if args.mode == "setCurrentRatio":
            value_high, value_low = split_uint16(args.value, "Current ratio")
            return build_ef5600_control_block(EF5600_ACTION_SET_SETTING, EF5600_CURRENT_RATIO_ADDRESS, value_high, value_low), {}
        if args.mode == "queryOvercurrent":
            return build_ef5600_control_block(EF5600_ACTION_QUERY_SETTING, EF5600_OVERCURRENT_ADDRESS), {}
        if args.mode == "setOvercurrent":
            return build_ef5600_control_block(EF5600_ACTION_SET_SETTING, EF5600_OVERCURRENT_ADDRESS, require_uint8(args.percent, "Overcurrent percent"), require_uint8(args.delaySeconds, "Overcurrent delay")), {}
        if args.mode == "queryOvervoltage":
            return build_ef5600_control_block(EF5600_ACTION_QUERY_SETTING, EF5600_OVERVOLTAGE_ADDRESS), {}
        if args.mode == "setOvervoltage":
            return build_ef5600_control_block(EF5600_ACTION_SET_SETTING, EF5600_OVERVOLTAGE_ADDRESS, require_uint8(args.percent, "Overvoltage percent"), require_uint8(args.delaySeconds, "Overvoltage delay")), {}
        if args.mode == "queryUndervoltage":
            return build_ef5600_control_block(EF5600_ACTION_QUERY_SETTING, EF5600_UNDERVOLTAGE_ADDRESS), {}
        if args.mode == "setUndervoltage":
            return build_ef5600_control_block(EF5600_ACTION_SET_SETTING, EF5600_UNDERVOLTAGE_ADDRESS, require_uint8(args.percent, "Undervoltage percent"), require_uint8(args.delaySeconds, "Undervoltage delay")), {}
        if args.mode == "queryOvertemperature":
            return build_ef5600_control_block(EF5600_ACTION_QUERY_SETTING, EF5600_OVERTEMPERATURE_ADDRESS), {}
        if args.mode == "setOvertemperature":
            return build_ef5600_control_block(EF5600_ACTION_SET_SETTING, EF5600_OVERTEMPERATURE_ADDRESS, require_uint8(args.temperature, "Overtemperature threshold"), require_uint8(args.delaySeconds, "Overtemperature delay")), {}
        if args.mode == "queryTempHumidity":
            return build_ef5600_control_block(EF5600_ACTION_QUERY_SETTING, EF5600_TEMP_HUMIDITY_ADDRESS), {}
        if args.mode == "setTempHumidity":
            return build_ef5600_control_block(EF5600_ACTION_SET_SETTING, EF5600_TEMP_HUMIDITY_ADDRESS, require_uint8(args.temperature, "Temperature threshold"), require_uint8(args.humidity, "Humidity threshold")), {}
        if args.mode == "queryLeakage":
            return build_ef5600_control_block(EF5600_ACTION_QUERY_SETTING, EF5600_LEAKAGE_ADDRESS), {}
        if args.mode == "setLeakage":
            value_high, value_low = split_uint16(args.value, "Leakage threshold")
            return build_ef5600_control_block(EF5600_ACTION_SET_SETTING, EF5600_LEAKAGE_ADDRESS, value_high, value_low), {}
    if sensor_type == DS103_SENSOR_TYPE:
        if args.mode == "switch":
            switch_target = parse_ds103_switch_target(args.channel)
            desired_state = 1 if str(args.value).strip().lower() in {"1", "true", "on", "yes"} else 0
            control_mode = 0 if desired_state else 1
            target = build_ds103_control_block(switch_target, desired_state, mode=control_mode, delay_seconds=0)
            return target, build_ds103_switch_confirmation(switch_target, bool(desired_state))
        if args.mode == "lock":
            desired_state = coerce_cli_value(args.value, entries_by_name["lockState"])
            target = build_ds103_control_block(254, desired_state, mode=0)
            return target, {"lockState": desired_state}
        if args.mode == "switchDelay":
            desired_state = 1 if str(args.value).strip().lower() in {"1", "true", "on", "yes"} else 0
            target = build_ds103_control_block(
                parse_ds103_switch_target(args.channel),
                desired_state,
                mode=1,
                delay_seconds=args.delaySeconds,
            )
            return target, {}
        if args.mode == "switchSchedule":
            desired_state = 1 if str(args.value).strip().lower() in {"1", "true", "on", "yes"} else 0
            target = build_ds103_control_block(
                parse_ds103_switch_target(args.channel),
                desired_state,
                mode=2,
                schedule_timestamp=args.scheduleTimestamp,
                repeat_daily=args.repeatDaily,
            )
            return target, {}
        if args.mode == "lockDelay":
            target = build_ds103_control_block(
                254,
                1 if str(args.value).strip().lower() in {"1", "true", "on", "yes"} else 0,
                mode=1,
                delay_seconds=args.delaySeconds,
            )
            return target, {}
        if args.mode == "lockSchedule":
            target = build_ds103_control_block(
                254,
                1 if str(args.value).strip().lower() in {"1", "true", "on", "yes"} else 0,
                mode=2,
                schedule_timestamp=args.scheduleTimestamp,
                repeat_daily=args.repeatDaily,
            )
            return target, {}
        if args.mode == "cancelSwitchTimer":
            target = build_ds103_control_block(parse_ds103_switch_target(args.channel), 0, mode=3)
            return target, {}
        if args.mode == "cancelLockTimer":
            return build_ds103_control_block(254, 0, mode=3), {}
        if args.mode == "query":
            return build_ds103_control_block(255, 0, mode=4), {}
    if args.mode == "power":
        target = {"powerState": coerce_cli_value(args.value, entries_by_name["powerState"])}
        return target, dict(target)
    if args.mode == "climate":
        target = {
            "setTemperature": coerce_cli_value(args.setTemperature, entries_by_name["setTemperature"]),
            "workMode": coerce_cli_value(args.workMode, entries_by_name["workMode"]),
            "fanSpeed": coerce_cli_value(args.fanSpeed, entries_by_name["fanSpeed"]),
        }
        return target, dict(target)
    target = {"keyLockState": coerce_cli_value(args.value, entries_by_name["keyLockState"])}
    return target, dict(target)


def build_control_attempt_plans(args, entries_by_name, sensor_type):
    expected, confirm_expected = build_control_plan(args, entries_by_name, sensor_type)
    plans = [
        {
            "label": "default",
            "expected": expected,
            "confirm_expected": confirm_expected,
        }
    ]

    if sensor_type == DS103_SENSOR_TYPE and args.mode == "switch":
        switch_target = parse_ds103_switch_target(args.channel)
        desired_state = 1 if str(args.value).strip().lower() in {"1", "true", "on", "yes"} else 0
        if not desired_state:
            confirm_map = build_ds103_switch_confirmation(switch_target, False)
            plans = [
                {
                    "label": "immediate-off",
                    "expected": build_ds103_control_block(switch_target, 0, mode=0, delay_seconds=0),
                    "confirm_expected": confirm_map,
                },
                {
                    "label": "delayed-off-1s",
                    "expected": build_ds103_control_block(switch_target, 0, mode=1, delay_seconds=1),
                    "confirm_expected": confirm_map,
                },
                {
                    "label": "delayed-off-5s",
                    "expected": build_ds103_control_block(switch_target, 0, mode=1, delay_seconds=5),
                    "confirm_expected": confirm_map,
                },
            ]

    if sensor_type == EF5600_SENSOR_TYPE and args.mode in {"breakerOpen", "breakerClose"}:
        plans = [
            {
                "label": "default",
                "expected": expected,
                "confirm_expected": confirm_expected,
            }
        ]

    return plans


def read_current_values(client, slave_id, entries_by_name, target_map):
    observed = {}
    for attribute_name in target_map:
        entry = entries_by_name[attribute_name]
        response = read_holding_registers_compat(client, entry["offset"], entry["register_count"], slave_id)
        if response.isError():
            observed[attribute_name] = None
            continue
        observed[attribute_name] = decode_modbus_registers(response.registers, entry)
    return observed


def all_targets_match(observed, expected, entries_by_name):
    for attribute_name, expected_value in expected.items():
        entry = entries_by_name[attribute_name]
        if not entry.get("confirm_required", True):
            continue
        if not values_match(expected_value, observed.get(attribute_name), entry):
            return False
    return True


def print_value_map(title, value_map, entries_by_name):
    print(title)
    for attribute_name, value in value_map.items():
        print(f"  {attribute_name}: {format_value(value, entries_by_name[attribute_name])}")


def wait_for_confirmation(client, slave_id, entries_by_name, expected):
    if not expected:
        return True, {}, 0.0

    started_at = time.perf_counter()
    last_observed = {}

    while True:
        last_observed = read_current_values(client, slave_id, entries_by_name, expected)
        if all_targets_match(last_observed, expected, entries_by_name):
            return True, last_observed, time.perf_counter() - started_at

        elapsed = time.perf_counter() - started_at
        if elapsed >= DEFAULT_CONFIRM_WINDOW_SECONDS:
            return False, last_observed, elapsed

        time.sleep(DEFAULT_CONFIRM_POLL_SECONDS)


def main():
    parser = argparse.ArgumentParser(
        description="Modbus TCP writer for W8004, AN-307, DS-501, DS-103 and EF5600 controls",
        epilog=HELP_EXAMPLES,
        formatter_class=argparse.RawTextHelpFormatter,
    )
    parser.add_argument("--ip", required=True, help="Gateway IP address")
    parser.add_argument("--port", type=int, help="Modbus TCP port")
    parser.add_argument("--slaveId", dest="slaveId", type=int, help="Modbus slave ID")
    parser.add_argument("--sensorType", dest="sensorType", help="Optional sensor model only: W8004, AN-201G, AN-307, DS-501, DS-103, EF5600-DN1")

    subparsers = parser.add_subparsers(dest="mode", required=True)

    power_parser = subparsers.add_parser("power", help="Write W8004 powerState")
    power_parser.add_argument("--value", default=str(int(DEFAULT_POWER_VALUE)), help="0/1 or false/true, default 1")

    climate_parser = subparsers.add_parser("climate", help="Write setTemperature, workMode, fanSpeed")
    climate_parser.add_argument("--setTemperature", default=str(DEFAULT_SET_TEMPERATURE), help="Target setTemperature, default 26.0")
    climate_parser.add_argument("--workMode", default=str(DEFAULT_WORK_MODE), help="Target workMode: 0-3, default 1")
    climate_parser.add_argument("--fanSpeed", default=str(DEFAULT_FAN_SPEED), help="Target fanSpeed: 0-4, default 1")

    lock_parser = subparsers.add_parser("lock", help="Write keyLockState")
    lock_parser.add_argument("--value", default=str(int(DEFAULT_LOCK_VALUE)), help="0/1, default 1")

    alarm_parser = subparsers.add_parser("alarm", help="Write AN-307 alarmStatus and optional alarmDurationSeconds")
    alarm_parser.add_argument("--value", default=str(int(DEFAULT_ALARM_VALUE)), help="0/1 or false/true, default 1")
    alarm_parser.add_argument("--durationSeconds", type=str, help="Optional auto-off duration in seconds when value=1")

    switch_parser = subparsers.add_parser("switch", help="Write DS-501 socket or DS-103 switch state")
    switch_parser.add_argument("--channel", default=DEFAULT_DS103_SWITCH_TARGET, help="1/2/3/all")
    switch_parser.add_argument("--value", required=True, help="0/1 or false/true")

    switch_delay_parser = subparsers.add_parser("switchDelay", help="Write DS-501 socket or DS-103 delayed switch command")
    switch_delay_parser.add_argument("--channel", default=DEFAULT_DS103_SWITCH_TARGET, help="1/2/3/all")
    switch_delay_parser.add_argument("--value", required=True, help="0/1 or false/true")
    switch_delay_parser.add_argument("--delaySeconds", required=True, type=int, help="Delay time in seconds")

    switch_schedule_parser = subparsers.add_parser("switchSchedule", help="Write DS-501 socket or DS-103 scheduled switch command")
    switch_schedule_parser.add_argument("--channel", default=DEFAULT_DS103_SWITCH_TARGET, help="1/2/3/all")
    switch_schedule_parser.add_argument("--value", required=True, help="0/1 or false/true")
    switch_schedule_parser.add_argument("--scheduleTimestamp", required=True, type=int, help="Unix timestamp in seconds")
    switch_schedule_parser.add_argument("--repeatDaily", action="store_true", default=DEFAULT_DS103_REPEAT_DAILY, help="Repeat every day")

    lock_delay_parser = subparsers.add_parser("lockDelay", help="Write DS-103 delayed lock command")
    lock_delay_parser.add_argument("--value", required=True, help="0/1 or false/true (0=unlock, 1=lock)")
    lock_delay_parser.add_argument("--delaySeconds", required=True, type=int, help="Delay time in seconds")

    lock_schedule_parser = subparsers.add_parser("lockSchedule", help="Write DS-103 scheduled lock command")
    lock_schedule_parser.add_argument("--value", required=True, help="0/1 or false/true (0=unlock, 1=lock)")
    lock_schedule_parser.add_argument("--scheduleTimestamp", required=True, type=int, help="Unix timestamp in seconds")
    lock_schedule_parser.add_argument("--repeatDaily", action="store_true", default=DEFAULT_DS103_REPEAT_DAILY, help="Repeat every day")

    cancel_switch_timer_parser = subparsers.add_parser("cancelSwitchTimer", help="Cancel DS-501 socket or DS-103 switch timer command")
    cancel_switch_timer_parser.add_argument("--channel", help="1/2/3/all")

    subparsers.add_parser("cancelLockTimer", help="Cancel DS-103 lock timer command")
    subparsers.add_parser("query", help="Query DS-103 switch state")

    subparsers.add_parser("reset", help="Send EF5600 remote reset command")
    subparsers.add_parser("selfTest", help="Send EF5600 remote selfTest command")
    subparsers.add_parser("silence", help="Send EF5600 remote silence command")
    subparsers.add_parser("breakerOpen", help="Send EF5600 remote breaker open command")
    subparsers.add_parser("breakerClose", help="Send EF5600 remote breaker close command")
    subparsers.add_parser("queryCurrentRatio", help="Query EF5600 current ratio setting")
    set_current_ratio_parser = subparsers.add_parser("setCurrentRatio", help="Set EF5600 current ratio")
    set_current_ratio_parser.add_argument("--value", required=True, type=int, help="Current ratio value, 0-65535")
    subparsers.add_parser("queryOvercurrent", help="Query EF5600 overcurrent alarm setting")
    set_overcurrent_parser = subparsers.add_parser("setOvercurrent", help="Set EF5600 overcurrent alarm percent and delay")
    set_overcurrent_parser.add_argument("--percent", required=True, type=int, help="Percent threshold, 0-255")
    set_overcurrent_parser.add_argument("--delaySeconds", required=True, type=int, help="Delay seconds, 0-255")
    subparsers.add_parser("queryOvervoltage", help="Query EF5600 overvoltage alarm setting")
    set_overvoltage_parser = subparsers.add_parser("setOvervoltage", help="Set EF5600 overvoltage alarm percent and delay")
    set_overvoltage_parser.add_argument("--percent", required=True, type=int, help="Percent threshold, 0-255")
    set_overvoltage_parser.add_argument("--delaySeconds", required=True, type=int, help="Delay seconds, 0-255")
    subparsers.add_parser("queryUndervoltage", help="Query EF5600 undervoltage alarm setting")
    set_undervoltage_parser = subparsers.add_parser("setUndervoltage", help="Set EF5600 undervoltage alarm percent and delay")
    set_undervoltage_parser.add_argument("--percent", required=True, type=int, help="Percent threshold, 0-255")
    set_undervoltage_parser.add_argument("--delaySeconds", required=True, type=int, help="Delay seconds, 0-255")
    subparsers.add_parser("queryOvertemperature", help="Query EF5600 overtemperature alarm setting")
    set_overtemperature_parser = subparsers.add_parser("setOvertemperature", help="Set EF5600 overtemperature alarm threshold and delay")
    set_overtemperature_parser.add_argument("--temperature", required=True, type=int, help="Temperature threshold, 0-255")
    set_overtemperature_parser.add_argument("--delaySeconds", required=True, type=int, help="Delay seconds, 0-255")
    subparsers.add_parser("queryTempHumidity", help="Query EF5600 temperature and humidity alarm setting")
    set_temp_humidity_parser = subparsers.add_parser("setTempHumidity", help="Set EF5600 temperature and humidity alarm thresholds")
    set_temp_humidity_parser.add_argument("--temperature", required=True, type=int, help="Temperature threshold, 0-255")
    set_temp_humidity_parser.add_argument("--humidity", required=True, type=int, help="Humidity threshold, 0-255")
    subparsers.add_parser("queryLeakage", help="Query EF5600 leakage alarm setting")
    set_leakage_parser = subparsers.add_parser("setLeakage", help="Set EF5600 leakage alarm threshold in mA")
    set_leakage_parser.add_argument("--value", required=True, type=int, help="Leakage threshold, 0-65535")

    args = parser.parse_args()

    requested_sensor = args.sensorType or "W8004"
    sensor_type = resolve_sensor_type_name(UCI_SNAPSHOT, args.sensorType, W8004_SENSOR_TYPE)
    if sensor_type not in DEVICE_SPECS:
        if sensor_type in READ_ONLY_SENSOR_TYPES:
            sensor_label = get_sensor_display_name(UCI_SNAPSHOT, sensor_type)
            print(f"Error: Sensor model '{sensor_label}' is telemetry-only and does not support Modbus TCP write operations.")
            sys.exit(1)
        print(f"Error: Unsupported sensor model '{requested_sensor}'.")
        sys.exit(1)

    spec = DEVICE_SPECS[sensor_type]
    sensor_label = get_sensor_display_name(UCI_SNAPSHOT, sensor_type)
    if args.mode not in spec["modes"]:
        allowed = ", ".join(sorted(spec["modes"]))
        print(f"Error: Mode '{args.mode}' is not supported for {sensor_label}. Allowed modes: {allowed}")
        sys.exit(1)

    if sensor_type == DS103_SENSOR_TYPE and args.mode == "cancelSwitchTimer" and not args.channel:
        print("Error: --channel is required for DS-103 cancelSwitchTimer.")
        sys.exit(1)

    port = args.port or get_snapshot_global_int(UCI_SNAPSHOT, "default_modbus_tcp_port", DEFAULT_MODBUS_PORT)
    slave_id = args.slaveId or get_snapshot_global_int(UCI_SNAPSHOT, "default_modbus_tcp_slave_id", DEFAULT_MODBUS_SLAVE_ID)

    layout = build_modbus_layout_from_snapshot(sensor_type, spec["layout"])
    entries_by_name = {entry["name"]: entry for entry in layout}
    attempt_plans = build_control_attempt_plans(args, entries_by_name, sensor_type)
    expected = attempt_plans[0]["expected"]
    confirm_expected = attempt_plans[0]["confirm_expected"]

    client = ModbusTcpClient(args.ip, port=port, timeout=3.0)
    if not client.connect():
        print(f"Connection Failed: Unable to connect to {args.ip}:{port}")
        sys.exit(1)

    overall_started_at = time.perf_counter()
    try:
        expected_version = get_sensor_profile_version(UCI_SNAPSHOT, sensor_type)
        expected_layout_hash = compute_modbus_layout_hash(layout, UCI_SNAPSHOT, sensor_type)
        remote_header = read_remote_protocol_header(client, slave_id)
        if expected_version or expected_layout_hash:
            if not remote_header:
                print(
                    "Error: Gateway service did not expose a valid fixed Modbus protocol header at registers "
                    f"0-{MODBUS_DEVICE_META_HEADER_REG_COUNT - 1}. "
                    "The running iot_hub service is likely too old for this script."
                )
                sys.exit(2)
            if remote_header["layoutHash"] != expected_layout_hash:
                print(
                    f"Error: Modbus layout hash mismatch for {sensor_label}. "
                    f"Script expects {expected_layout_hash}, gateway exposes {remote_header['layoutHash']}. "
                    "Please update the Python scripts or restart iot_hub with the matching protocol mapping."
                )
                sys.exit(2)
            if expected_version and remote_header["profileVersion"] != expected_version:
                print(
                    f"Error: Profile version mismatch for {sensor_label}. "
                    f"Script expects {expected_version}, gateway exposes {remote_header['profileVersion']}. "
                    "Please update the Python scripts or restart iot_hub with the matching protocol mapping."
                )
                sys.exit(2)

        print(f"Target: {args.ip}:{port} | Slave ID: {slave_id} | Sensor: {sensor_label}")
        print_value_map("Expected values:", expected, entries_by_name)
        if confirm_expected and confirm_expected != expected:
            print_value_map("Expected confirmed state:", confirm_expected, entries_by_name)

        for attempt, attempt_plan in enumerate(attempt_plans, start=1):
            print(f"Attempt {attempt}/{len(attempt_plans)}: writing control values ({attempt_plan['label']})...")
            attempt_started_at = time.perf_counter()
            write_failed = False
            write_batches = build_write_batches(attempt_plan["expected"], entries_by_name)

            if attempt_plan["expected"] != expected:
                print_value_map("Attempt values:", attempt_plan["expected"], entries_by_name)

            describe_modbus_batches(write_batches)

            for batch in write_batches:
                response = write_registers_compat(client, batch["offset"], batch["values"], slave_id)
                if response.isError():
                    joined_names = ", ".join(batch["names"])
                    print(f"  Write failed for {joined_names}: {response}")
                    write_failed = True
                    break

            if not write_failed:
                if not attempt_plan["confirm_expected"]:
                    total_elapsed = time.perf_counter() - overall_started_at
                    print("No immediate read-back confirmation defined for this command.")
                    print(f"Control completed in: {total_elapsed:.3f}s")
                    return

                confirmed, observed, confirm_elapsed = wait_for_confirmation(client, slave_id, entries_by_name, attempt_plan["confirm_expected"])
                if confirmed:
                    total_elapsed = time.perf_counter() - overall_started_at
                    print_value_map("Observed values:", observed, entries_by_name)
                    print(f"Link confirmation time: {confirm_elapsed:.3f}s")
                    print(f"Control completed in: {total_elapsed:.3f}s")
                    return

                print_value_map("Observed values after retry window:", observed, entries_by_name)
                print(f"  No confirmation within {confirm_elapsed:.3f}s.")
            else:
                print(f"  Attempt {attempt} write failed before confirmation polling.")

            print(f"  Attempt elapsed: {time.perf_counter() - attempt_started_at:.3f}s")

        print(f"Control failed after {len(attempt_plans)} attempts.")
        sys.exit(2)
    finally:
        client.close()


if __name__ == "__main__":
    main()