UNPKG

homebridge-cmd4

Version:

Exec Plugin for Homebridge supporting all accessorys and characteristics

1,666 lines (1,279 loc) 116 kB
#!/usr/bin/env node // State.js // // Description: // This script *CAN* be called by the HomeBridge plugin Cmd4 as defined in your config.json // file. The purpose is to fake the existance of an accessory or to be modified by you // such that acessories can Get/Set characteristics as defined in the HomeKit Accessory // Specifications. // // Plugin Installation: // - npm install [-g] Cmd4 // - mkdir $HOME/.homebridge/Cmd4Scripts // - cp State.js $HOME/.homebridge/Cmd4Scripts/State.js // - chmod u+x $HOME/.homebridge/Cmd4Scripts/State.js // // Parameters are: // Get <accessory name> <characteristic> // Set <accessory name> <characteristic> <value> // // Note 1: These paramaters match the those of the Cmd4 plugin. // Note 2: All characteristics of the HomeKit Accessory Protocol (HAP) // specifications are supported, except for camera streaming; // Though I have found some like LockManagement are not within IOS. // Side Note: The Eve app is nicer, try it. // Note 3: The Hap spec is quoted throughout, but this is not the spec so // this is not gauranteed to be correct. // Note 4: In this latest version, State.js does not care which characteristic // belongs with a specific accessssory for the purpose of creating // custom accessories. IOS would not like this, but if you use // the provided config.json file that defines the corrrect characteristics, // this will not matter. // // How it works: // A characteristic value is stored in the $HOME/.homebridge/Cmd4Scripts/Cmd4States in // the file named "Status + <Accessory Name> _ <Characteristic>" and is returned or // written to based on the <Get|Set> option. // // For example: node State.js Set My_Door MotionDetected 0 // will create the file .homebridge/Cmd4Scripts/Cmd4States/My_Door_MotionDetected // with the contents of "0" // Note: See how this is run from $HOME (Important!) // // Environmental Variables Used: // $HOME - to create path to .homebridge // // // Interesting fact. If you use characteristics as is, and define all possible accessories in your config.json // file, they will all appear fully functional within HomeKit. In this way you // can play with HomeKit and not have any physical devices at all. Cool Eh! // // *IMPORTANT* - I cannot audit commented constants. The lib/CMD4_DEVICE_ENUM.js is what is used // for constant translations. 'use strict'; // FileSystem requirements. var fs = require('fs'); var path = require('path'); var os = require('os'); // The files created within Cmd4StatesPath contain just a value of the accessories last state, // so they are very small in size. var Cmd4StatesPath = path.join(os.homedir(), ".homebridge/Cmd4Scripts/Cmd4States"); var length = process.argv.length; var device = ""; var io = ""; var characteristic = ""; var option = ""; if ( length == 2 ) process.exit( 0 ); if ( length <= 2 ) { process.stdout.write( `Usage: ${ process.argv[ 0 ] } <Get> <AccessoryName> <Characteristic>` ); process.stdout.write( ` ${ process.argv[ 0 ] } <Set> <AccessoryName> <Characteristic> <Value>` ); process.exit(-1); } if ( length >= 2 ) io = process.argv[ 2 ]; if ( length >= 3 ) device = process.argv[ 3 ]; if ( length >= 4 ) characteristic = process.argv[ 4 ]; if ( length >= 5 ) option = process.argv[ 5 ]; // Placing the states in a subdirectory makes things look cleaner. // Some platforms require an exception handler const mkdirSync = function( dirPath ) { try { fs.mkdirSync( dirPath ) } catch ( err ) { if ( err.code !== 'EEXIST' ) { process.stdout.write( `mkdir failed: ${ dirPath }`); throw err; } else { // directory already exists - OK } } } mkdirSync( Cmd4StatesPath ); // Such a simple way to store state information that is small and fast! // Put exception handling here too. Just in case! function writeData( a, b,c ) { var fn = Cmd4StatesPath + "/Status_" + a + "_" + b; try { fs.writeFileSync( fn,c ); } catch (err) { if ( err.code !== 'EEXIST' ) { process.stdout.write( `write data failed: ${ fn } data: ${ c }` ); throw err; } else { // file already exists - OK } } } // Read the state information. If there is none, just return what // was expected. // Put exception handling here too. Just in case! function readData( a, b ) { var fn = Cmd4StatesPath + "/Status_" + a + "_" + b; c = ""; try { c = String( fs.readFileSync( fn, 'utf8' ) ); } catch (err) { if ( err.code === 'ENOENT' ) { // This is OK. just return what was expected. return c; } else { if ( err.code !== 'EEXIST' ) { process.stdout.write( `read data failed: ${ fn }` ); throw err; } else { // file already exists - OK } } } return c; } var c = ""; switch( io ) { case "Get": { switch( characteristic ) { case "AccessControlLevel": // 0 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( `1` ); else process.stdout.write( `"${ c }"` ); // To avoid hard coding values, characteristic definitions can be found in: // Cmd4 Github pages -> http://ztalbot2000.github.io/homebridge-cmd4 // Homebridge developer documentation -> https://developers.homebridge.io/#/ break; } case "AccessoryFlags": // 1 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "1" ); else process.stdout.write( `"${ c }"` ); break; } case "AccessoryIdentifier": // 2 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "TLB" ); else process.stdout.write( `"${ c }"` ); break; } case "Active": // 3 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "1" ); else process.stdout.write( `"${ c }"` ); break; } case "ActiveIdentifier": // 4 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "1" ); else process.stdout.write( `"${ c }"` ); break; } case "ActivityInterval": // 5 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "1" ); else process.stdout.write( `"${ c }"` ); break; } case "AdministratorOnlyAccess": // 6 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "0" ); else process.stdout.write( `"${ c }"` ); break; } case "AirParticulateDensity": // 7 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "30" ); else process.stdout.write( `"${ c }"` ); break; } case "AirParticulateSize": // 8 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "0" ); else process.stdout.write( `"${ c }"` ); break; } case "AirQuality": // 9 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "1" ); else process.stdout.write( `"${ c }"` ); break; } case "AppMatchingIdentifier": // 10 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "0" ); else process.stdout.write( `"${ c }"` ); break; } case "AudioFeedback": // 11 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "0" ); else process.stdout.write( `"${ c }"` ); break; } case "BatteryLevel": // 12 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "50" ); else process.stdout.write( `"${ c }"` ); break; } case "Brightness": // 13 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "100" ); else process.stdout.write( `"${ c }"` ); break; } case "ButtonEvent": // 14 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "0" ); else process.stdout.write( `"${ c }"` ); break; } case "CCAEnergyDetectThreshold": // 15 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "1" ); else process.stdout.write( `"${ c }"` ); break; } case "CCASignalDetectThreshold": // 16 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "1" ); else process.stdout.write( `"${ c }"` ); break; } case "CameraOperatingModeIndicator": // 17 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "100" ); else process.stdout.write( `"${ c }"` ); break; } case "CarbonDioxideDetected": // 18 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "0" ); else process.stdout.write( `"${ c }"` ); break; } case "CarbonDioxideLevel": // 19 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "0" ); else process.stdout.write( `"${ c }"` ); break; } case "CarbonDioxidePeakLevel": // 20 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "0" ); else process.stdout.write( `"${ c }"` ); break; } case "CarbonMonoxideDetected": // 21 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "0" ); else process.stdout.write( `"${ c }"` ); break; } case "CarbonMonoxideLevel": // 22 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "0" ); else process.stdout.write( `"${ c }"` ); break; } case "CarbonMonoxidePeakLevel": // 23 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "0" ); else process.stdout.write( `"${ c }"` ); break; } case "Category": // 24 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "1" ); else process.stdout.write( `"${ c }"` ); break; } case "CharacteristicValueTransitionControl": // 25 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "0" ); else process.stdout.write( `"${ c }"` ); break; } case "ChargingState": // 26 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "0" ); else process.stdout.write( `"${ c }"` ); break; } case "ClosedCaptions": // 27 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "0" ); else process.stdout.write( `"${ c }"` ); break; } case "ColorTemperature": // 28 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "50" ); else process.stdout.write( `"${ c }"` ); break; } case "ConfigureBridgedAccessory": // 29 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "0" ); else process.stdout.write( `"${ c }"` ); break; } case "ConfigureBridgedAccessoryStatus": // 30 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "0" ); else process.stdout.write( `"${ c }"` ); break; } case "ConfiguredName": // 31 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( `"${ device }"` ); else process.stdout.write(`"${ c }"` ); break; } case "ContactSensorState": // 32 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "0" ); else process.stdout.write( `"${ c }"` ); break; } case "CoolingThresholdTemperature": // 33 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "32.4" ); else process.stdout.write( `"${ c }"` ); break; } case "CurrentAirPurifierState": // 34 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "2" ); else process.stdout.write( `"${ c }"` ); break; } case "CurrentAmbientLightLevel": // 35 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "1" ); else process.stdout.write( `"${ c }"` ); break; } case "CurrentDoorState": // 36 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "0" ); else process.stdout.write( `"${ c }"` ); break; } case "CurrentFanState": // 37 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "1" ); else process.stdout.write( `"${ c }"` ); break; } case "CurrentHeaterCoolerState": // 38 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "0" ); else process.stdout.write( `"${ c }"` ); process.exit(0); break; } case "CurrentHeatingCoolingState": // 39 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "0" ); else process.stdout.write( `"${ c }"` ); process.exit(0); break; } case "CurrentHorizontalTiltAngle": // 40 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "0" ); else process.stdout.write( `"${ c }"` ); break; } case "CurrentHumidifierDehumidifierState": // 41 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "1" ); else process.stdout.write( `"${ c }"` ); break; } case "CurrentMediaState": // 42 { c = readData( device, characteristic ); //validValues: // "PLAY" // "PAUSE" // "STOP" // "LOADING" // "INTERRUPTED" if ( c == "" ) process.stdout.write( "STOP" ); else process.stdout.write( `"${ c }"` ); break; } case "CurrentPosition": // 43 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "0" ); else process.stdout.write( `"${ c }"` ); break; } case "CurrentRelativeHumidity": // 44 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "60.2" ); else process.stdout.write( `"${ c }"` ); break; } case "CurrentSlatState": // 45 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "0" ); else process.stdout.write( `"${ c }"` ); break; } case "CurrentTemperature": // 46 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "22.2" ); else process.stdout.write( `"${ c }"` ); break; } case "CurrentTiltAngle": // 47 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "0" ); else process.stdout.write( `"${ c }"` ); break; } case "CurrentTime": // 48 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "11.5" ); else process.stdout.write( `"${ c }"` ); break; } case "CurrentTransport": // 49 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "0" ); else process.stdout.write( `"${ c }"` ); break; } case "CurrentVerticalTiltAngle": // 50 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "0" ); else process.stdout.write( `"${ c }"` ); break; } case "CurrentVisibilityState": // 51 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "0" ); else process.stdout.write( `"${ c }"` ); break; } case "DataStreamHAPTransport": // 52 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "0" ); else process.stdout.write( `"${ c }"` ); break; } case "DataStreamHAPTransportInterrupt": // 53 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "0" ); else process.stdout.write( `"${ c }"` ); break; } case "DayoftheWeek": // 54 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "1" ); else process.stdout.write( `"${ c }"` ); break; } case "DiagonalFieldOfView": // 55 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "50" ); else process.stdout.write( `"${ c }"` ); break; } case "DigitalZoom": // 56 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "1" ); else process.stdout.write( `"${ c }"` ); break; } case "DiscoverBridgedAccessories": // 57 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "0" ); else process.stdout.write( `"${ c }"` ); break; } case "DiscoveredBridgedAccessories": // 58 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "0" ); else process.stdout.write( `"${ c }"` ); break; } case "DisplayOrder": // 59 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "0" ); else process.stdout.write( `"${ c }"` ); break; } case "EventRetransmissionMaximum": // 60 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "0" ); else process.stdout.write( `"${ c }"` ); break; } case "EventSnapshotsActive": // 61 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "0" ); else process.stdout.write( `"${ c }"` ); break; } case "EventTransmissionCounters": // 62 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "0" ); else process.stdout.write( `"${ c }"` ); break; } case "FilterChangeIndication": // 63 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "0" ); else process.stdout.write( `"${ c }"` ); break; } case "FilterLifeLevel": // 64 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "50" ); else process.stdout.write( `"${ c }"` ); break; } case "FirmwareRevision": // 65 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "100.1.1" ); else process.stdout.write( `"${ c }"` ); break; } case "HardwareRevision": // 66 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "100.1.1" ); else process.stdout.write( `"${ c }"` ); break; } case "HeartBeat": // 67 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "64" ); else process.stdout.write( `"${ c }"` ); break; } case "HeatingThresholdTemperature": // 68 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "25.2" ); else process.stdout.write( `"${ c }"` ); break; } case "HoldPosition": // 69 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "0" ); else process.stdout.write( `"${ c }"` ); break; } case "HomeKitCameraActive": // 70 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "0" ); else process.stdout.write( `"${ c }"` ); break; } case "Hue": // 71 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "50" ); else process.stdout.write( `"${ c }"` ); break; } case "Identifier": // 77 { c = readData( device, characteristic ); if ( c == "" ){ // Each identifier needs a unique number // Match this with what is in the config.json switch( device ) { case "HDMI1": process.stdout.write( "0" ); break; case "HDMI2": process.stdout.write( "1" ); break; case "HDMI3": process.stdout.write( "2" ); break; case "HDMI4": process.stdout.write( "3" ); break; case "Netflix": process.stdout.write( "4" ); break; default: process.stdout.write( "0" ); } } else { process.stdout.write( `"${ c }"` ); } break; } case "Identify": // 73 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "0" ); else process.stdout.write( `"${ c }"` ); break; } case "ImageMirroring": // 74 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "0" ); else process.stdout.write( `"${ c }"` ); break; } case "ImageRotation": // 75 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "0" ); else process.stdout.write( `"${ c }"` ); break; } case "InUse": // 76 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "1" ); else process.stdout.write( `"${ c }"` ); break; } case "InputDeviceType": // 77 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "1" ); else process.stdout.write( `"${ c }"` ); break; } case "InputSourceType": // 78 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "1" ); else process.stdout.write( `"${ c }"` ); break; } case "IsConfigured": // 79 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "1" ); else process.stdout.write( `"${ c }"` ); break; } case "LeakDetected": // 80 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "0" ); else process.stdout.write( `"${ c }"` ); break; } case "LinkQuality": // 81 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "0" ); else process.stdout.write( `"${ c }"` ); break; } case "ListPairings": // 82 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "0" ); else process.stdout.write( `"${ c }"` ); break; } case "LockControlPoint": // 83 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "0" ); else process.stdout.write( `"${ c }"` ); break; } case "LockCurrentState": // 84 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "0" ); else process.stdout.write( `"${ c }"` ); break; } case "LockLastKnownAction": // 85 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "0" ); else process.stdout.write( `"${ c }"` ); break; } case "LockManagementAutoSecurityTimeout": // 86 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "26" ); else process.stdout.write( `"${ c }"` ); break; } case "LockPhysicalControls": // 87 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "0" ); else process.stdout.write( `"${ c }"` ); break; } case "LockTargetState": // 88 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "0" ); else process.stdout.write( `"${ c }"` ); break; } case "Logs": // 89 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "0" ); else process.stdout.write( `"${ c }"` ); break; } case "MACRetransmissionMaximum": // 90 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "100" ); else process.stdout.write( `"${ c }"` ); break; } case "MACTransmissionCounters": // 91 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "100" ); else process.stdout.write( `"${ c }"` ); break; } case "ManagedNetworkEnable": // 92 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "0" ); else process.stdout.write( `"${ c }"` ); break; } case "ManuallyDisabled": // 93 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "0" ); else process.stdout.write( `"${ c }"` ); break; } case "Manufacturer": // 94 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "Homebridge" ); else process.stdout.write( `"${ c }"` ); break; } case "Model": // 95 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "1" ); else process.stdout.write( `"${ c }"` ); break; } case "MotionDetected": // 96 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "0" ); else process.stdout.write( `"${ c }"` ); break; } case "Mute": // 97 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "0" ); else process.stdout.write( `"${ c }"` ); break; } case "Name": // 98 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( `"${ device }"` ); else process.stdout.write( `"${ c }"` ); break; } case "NetworkAccessViolationControl": // 99 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "0" ); else process.stdout.write( `"${ c }"` ); break; } case "NetworkClientProfileControl": // 100 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "0" ); else process.stdout.write( `"${ c }"` ); break; } case "NetworkClientStatusControl": // 101 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "0" ); else process.stdout.write( `"${ c }"` ); break; } case "NightVision": // 102 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "1" ); else process.stdout.write( `"${ c }"` ); break; } case "NitrogenDioxideDensity": // 103 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "50.0" ); else process.stdout.write( `"${ c }"` ); break; } case "ObstructionDetected": // 104 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "0" ); else process.stdout.write( `"${ c }"` ); break; } case "OccupancyDetected": // 105 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "0" ); else process.stdout.write( `"${ c }"` ); break; } case "On": // 106 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "0" ); else process.stdout.write( `"${ c }"` ); break; } case "OperatingStateResponse": // 107 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "0" ); else process.stdout.write( `"${ c }"` ); break; } case "OpticalZoom": // 108 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "1.0" ); else process.stdout.write( `"${ c }"` ); break; } case "OutletInUse": // 109 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "0" ); else process.stdout.write( `"${ c }"` ); break; } case "OzoneDensity": // 110 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "50.0" ); else process.stdout.write( `"${ c }"` ); break; } case "PM10Density": // 111 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "50.0" ); else process.stdout.write( `"${ c }"` ); break; } case "PM2_5Density": // 112 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "50.0" ); else process.stdout.write( `"${ c }"` ); break; } case "PairSetup": // 113 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "0" ); else process.stdout.write( `"${ c }"` ); break; } case "PairVerify": // 114 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "0" ); else process.stdout.write( `"${ c }"` ); break; } case "PairingFeatures": // 115 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "0" ); else process.stdout.write( `"${ c }"` ); break; } case "PairingPairings": // 116 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "0" ); else process.stdout.write( `"${ c }"` ); break; } case "PasswordSetting": // 117 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "0" ); else process.stdout.write( `"${ c }"` ); break; } case "PeriodicSnapshotsActive": // 118 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "0" ); else process.stdout.write( `"${ c }"` ); break; } case "PictureMode": // 119 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "1" ); else process.stdout.write( `"${ c }"` ); break; } case "Ping": // 120 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "0" ); else process.stdout.write( `"${ c }"` ); break; } case "PositionState": // 121 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "2" ); else process.stdout.write( `"${ c }"` ); break; } case "PowerModeSelection": // 122 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "1" ); else process.stdout.write( `"${ c }"` ); break; } case "ProductData": // 123 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "1" ); else process.stdout.write( `"${ c }"` ); break; } case "ProgramMode": // 124 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "0" ); else process.stdout.write( `"${ c }"` ); break; } case "ProgrammableSwitchEvent": // 125 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "0" ); else process.stdout.write( `"${ c }"` ); break; } case "ProgrammableSwitchOutputState": // 126 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "0" ); else process.stdout.write( `"${ c }"` ); break; } case "Reachable": // 127 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "1" ); else process.stdout.write( `"${ c }"` ); break; } case "ReceivedSignalStrengthIndication": // 128 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "1" ); else process.stdout.write( `"${ c }"` ); break; } case "ReceiverSensitivity": // 129 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "1" ); else process.stdout.write( `"${ c }"` ); break; } case "RecordingAudioActive": // 130 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "1" ); else process.stdout.write( `"${ c }"` ); break; } case "RelativeHumidityDehumidifierThreshold": // 131 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "1" ); else process.stdout.write( `"${ c }"` ); break; } case "RelativeHumidityHumidifierThreshold": // 132 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "1" ); else process.stdout.write( `"${ c }"` ); break; } case "RelayControlPoint": // 133 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "0" ); else process.stdout.write( `"${ c }"` ); break; } case "RelayEnabled": // 134 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "1" ); else process.stdout.write( `"${ c }"` ); break; } case "RelayState": // 135 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "1" ); else process.stdout.write( `"${ c }"` ); break; } case "RemainingDuration": // 136 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "1" ); else process.stdout.write( `"${ c }"` ); break; } case "RemoteKey": // 137 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "1" ); else process.stdout.write( `"${ c }"` ); break; } case "ResetFilterIndication": // 138 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "0" ); else process.stdout.write( `"${ c }"` ); break; } case "RotationDirection": // 139 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "0" ); else process.stdout.write( `"${ c }"` ); break; } case "RotationSpeed": // 140 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "100" ); else process.stdout.write( `"${ c }"` ); break; } case "RouterStatus": // 141 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "100" ); else process.stdout.write( `"${ c }"` ); break; } case "Saturation": // 142 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "50" ); else process.stdout.write( `"${ c }"` ); break; } case "SecuritySystemAlarmType": // 143 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "0" ); else process.stdout.write( `"${ c }"` ); break; } case "SecuritySystemCurrentState": // 144 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "3" ); else process.stdout.write( `"${ c }"` ); break; } case "SecuritySystemTargetState": // 145 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "0" ); else process.stdout.write( `"${ c }"` ); break; } case "SelectedAudioStreamConfiguration": // 146 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "0" ); else process.stdout.write( `"${ c }"` ); break; } case "SelectedCameraRecordingConfiguration": // 147 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "0" ); else process.stdout.write( `"${ c }"` ); break; } case "SelectedRTPStreamConfiguration": // 148 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "0" ); else process.stdout.write( `"${ c }"` ); break; } case "SerialNumber": // 149 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "ABC001" ); else process.stdout.write( `"${ c }"` ); break; } case "ServiceLabelIndex": // 150 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "0" ); else process.stdout.write( `"${ c }"` ); break; } case "ServiceLabelNamespace": // 151 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "0" ); else process.stdout.write( `"${ c }"` ); break; } case "SetDuration": // 152 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "1" ); else process.stdout.write( `"${ c }"` ); break; } case "SetupDataStreamTransport": // 153 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "0" ); else process.stdout.write( `"${ c }"` ); break; } case "SetupEndpoints": // 154 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "0" ); else process.stdout.write( `"${ c }"` ); break; } case "SetupTransferTransport": // 155 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "0" ); else process.stdout.write( `"${ c }"` ); break; } case "SignalToNoiseRatio": // 156 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "0" ); else process.stdout.write( `"${ c }"` ); break; } case "SiriInputType": // 157 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "0" ); else process.stdout.write( `"${ c }"` ); break; } case "SlatType": // 158 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "0" ); else process.stdout.write( `"${ c }"` ); break; } case "SleepDiscoveryMode": // 159 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "1" ); else process.stdout.write( `"${ c }"` ); break; } case "SleepInterval": // 160 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "1" ); else process.stdout.write( `"${ c }"` ); break; } case "SmokeDetected": // 161 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "0" ); else process.stdout.write( `"${ c }"` ); break; } case "SoftwareRevision": // 162 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "50" ); else process.stdout.write( `"${ c }"` ); break; } case "StatusActive": // 163 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "1" ); else process.stdout.write( `"${ c }"` ); break; } case "StatusFault": // 164 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "0" ); else process.stdout.write( `"${ c }"` ); break; } case "StatusJammed": // 165 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "0" ); else process.stdout.write( `"${ c }"` ); break; } case "StatusLowBattery": // 166 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "0" ); else process.stdout.write( `"${ c }"` ); break; } case "StatusTampered": // 167 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "0" ); else process.stdout.write( `"${ c }"` ); break; } case "StreamingStatus": // 168 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "0" ); else process.stdout.write( `"${ c }"` ); break; } case "SulphurDioxideDensity": // 169 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "50.0" ); else process.stdout.write( `"${ c }"` ); break; } case "SupportedAudioRecordingConfiguration": // 170 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "0" ); else process.stdout.write( `"${ c }"` ); break; } case "SupportedAudioStreamConfiguration": // 171 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "0" ); else process.stdout.write( `"${ c }"` ); break; } case "SupportedCameraRecordingConfiguration": // 172 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "0" ); else process.stdout.write( `"${ c }"` ); break; } case "SupportedDataStreamTransportConfiguration": // 173 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "0" ); else process.stdout.write( `"${ c }"` ); break; } case "SupportedCharacteristicValueTransitionConfiguration": // 174 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "0" ); else process.stdout.write( `"${ c }"` ); break; } case "SupportedDiagnosticsSnapshot": // 175 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "0" ); else process.stdout.write( `"${ c }"` ); break; } case "SupportedRTPConfiguration": // 176 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "0" ); else process.stdout.write( `"${ c }"` ); break; } case "SupportedRouterConfiguration": // 177 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "0" ); else process.stdout.write( `"${ c }"` ); break; } case "SupportedTransferTransportConfiguration": // 178 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "0" ); else process.stdout.write( `"${ c }"` ); break; } case "SupportedVideoRecordingConfiguration": // 179 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "0" ); else process.stdout.write( `"${ c }"` ); break; } case "SupportedVideoStreamConfiguration": // 180 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "0" ); else process.stdout.write( `"${ c }"` ); break; } case "SwingMode": // 181 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "100" ); else process.stdout.write( `"${ c }"` ); break; } case "TargetAirPurifierState": // 182 { c = readData( device, characteristic ); if ( c == "" ) process.stdout.write( "1" ); else process.stdout.write( `"${ c }"` ); break; } case "TargetAirQuality": // 183 { c