Package: pyLOOKinRemote
pyLOOKinRemoteUnofficial Python module for interacting with LOOKin Remote devices, largely using LOOKin's API:https://look-in.club/en/support/apiTo UseUse this class to interact with a LOOKin Remote device.  For example:from pylookinremote import LOOKinRemote

  devs = LOOKinRemote.findInNetwork()
  for dev in devs:
      meteoSensorMeas = dev.sensor('Meteo')
      temp_C = meteoSensorMeas['Temperature']
      temp_F = LOOKinRemote.celsius2Fahrenheit(meteoSensorMeas['Temperature'])
      humidityRel = meteoSensorMeas['Humidity']
      print(f'{dev!s} is reporting: {temp_C}°C/{temp_F:0.1f}°F and {humidityRel}%RH')This generates the output:Starting search for available LOOKinRemote devices...
  ...Device Found at 192.168.0.123...
  ...Device Found at 192.168.0.234...
  ...Search complete!  Found 2 LOOKin Remote devices.
  LOOKinRemote(192.168.0.123) is reporting: 20.7°C/69.3°F and 53.6%RH
  LOOKinRemote(192.168.0.234) is reporting: 21.0°C/69.8°F and 61.3%RHTo InstallInstall from PyPI usingpip:Linux:pip install pyLOOKinRemoteWindows:py -m pip install pyLOOKinRemoteTo UninstallUninstall usingpip:Linux:pip uninstall pyLOOKinRemoteWindows:py -m pip uninstall pyLOOKinRemoteAuxiliary Data FileOn-device function storage doesn't appear to be working right now, so this
script allows you to save and load function data through a JSON file instead.Learning Remote CommandsThis module offers an automated IR command learning method.from pylookinremote import LOOKinRemote

  auxDataFilePath='./auxData.json'  #File to save function data in.
  dev = LOOKinRemote('192.168.0.123', auxDataFilePath)
  remoteUUID = '1234'  #ID of the IR remote on the LOOKin Remote.
  newIRFunction = IRRemoteFunction.fromIRSensor(dev, 'myNewFunctionName')  #The "Learn IR Command" routine.
  if newIRFunction is not None:  #Capture was successful.
      try:  #The LOOKin Remote can get unstable during captures of long IR sequences, throwing connection errors.
          remote = dev.remoteFromUUID(remoteUUID)
          remote.functionUpdate(newIRFunction)
      except:  #Dump the JSON on error so it can be manually added and all that effort isn't lost.
          print(f'ERROR while saving function:  newIRFunction = {newIRFunction.toJSON()!r}')Executing the above script will generate something like the following (IR sequences have been shortened for this example):Learning new IR remote function 'myNewFunctionName'...
  ...Please trigger the desired IR remote function repeatedly on the target LOOKin Remote...
  Running sensor dump for 300 seconds...
  _get - url='http://192.168.0.123/sensors/IR'
  _get - url='http://192.168.0.123/sensors/IR'
  _get - url='http://192.168.0.123/sensors/IR'
  _get - url='http://192.168.0.123/sensors/IR'
  _get - url='http://192.168.0.123/sensors/IR'
  _get - url='http://192.168.0.123/sensors/IR'
  _get - url='http://192.168.0.123/sensors/IR'
  _get - url='http://192.168.0.123/sensors/IR'
  _get - url='http://192.168.0.123/sensors/IR'
  _get - url='http://192.168.0.123/sensors/IR'
  _get - url='http://192.168.0.123/sensors/IR'
  {'IsRepeated': '0', 'Protocol': '00', 'Raw': '470 -390 470 -390 470 -390 470 -390 470 -390 470 -45000', 'RepeatPause': '0', 'RepeatSignal': '', 'Signal': '0', 'Updated': '0'}
  _get - url='http://192.168.0.123/sensors/IR'
  _get - url='http://192.168.0.123/sensors/IR'
  {'IsRepeated': '0', 'Protocol': 'FF', 'Raw': '470 -390 470 -390 470 -390 470 -390 470 -390 470 -45000', 'RepeatPause': '0', 'RepeatSignal': '', 'Signal': '0', 'Updated': '1630995857'}
  _get - url='http://192.168.0.123/sensors/IR'
  _get - url='http://192.168.0.123/sensors/IR'
  _get - url='http://192.168.0.123/sensors/IR'
  _get - url='http://192.168.0.123/sensors/IR'
  _get - url='http://192.168.0.123/sensors/IR'
  _get - url='http://192.168.0.123/sensors/IR'
  {'IsRepeated': '0', 'Protocol': 'FF', 'Raw': '470 -390 470 -390 440 -420 470 -390 470 -390 470 -45000', 'RepeatPause': '0', 'RepeatSignal': '', 'Signal': '0', 'Updated': '1631003614'}
  _get - url='http://192.168.0.123/sensors/IR'
  _get - url='http://192.168.0.123/sensors/IR'
  _get - url='http://192.168.0.123/sensors/IR'
  _get - url='http://192.168.0.123/sensors/IR'
  _get - url='http://192.168.0.123/sensors/IR'
  _get - url='http://192.168.0.123/sensors/IR'
  _get - url='http://192.168.0.123/sensors/IR'
  _get - url='http://192.168.0.123/sensors/IR'
  {'IsRepeated': '0', 'Protocol': 'FF', 'Raw': '470 -390 470 -390 470 -390 470 -390 470 -390 470 -45000', 'RepeatPause': '0', 'RepeatSignal': '', 'Signal': '0', 'Updated': '1631009781'}
  _get - url='http://192.168.0.123/sensors/IR'
  _get - url='http://192.168.0.123/sensors/IR'
  _get - url='http://192.168.0.123/sensors/IR'
  _get - url='http://192.168.0.123/sensors/IR'
  _get - url='http://192.168.0.123/sensors/IR'
  _get - url='http://192.168.0.123/sensors/IR'
  Connection Reset!  The device might be restarting due to a crash.
  _get - url='http://192.168.0.123/sensors/IR'
  {'IsRepeated': '0', 'Protocol': 'FF', 'Raw': '470 -390 440 -420 470 -390 470 -390 470 -390 470 -45000', 'RepeatPause': '0', 'RepeatSignal': '', 'Signal': '0', 'Updated': '1631017192'}
  _get - url='http://192.168.0.123/sensors/IR'
  _get - url='http://192.168.0.123/sensors/IR'
  _get - url='http://192.168.0.123/sensors/IR'
  _get - url='http://192.168.0.123/sensors/IR'
  _get - url='http://192.168.0.123/sensors/IR'
  Connection Reset!  The device might be restarting due to a crash.
  _get - url='http://192.168.0.123/sensors/IR'
  _get - url='http://192.168.0.123/sensors/IR'
  _get - url='http://192.168.0.123/sensors/IR'
  _get - url='http://192.168.0.123/sensors/IR'
  _get - url='http://192.168.0.123/sensors/IR'
  {'IsRepeated': '0', 'Protocol': '00', 'Raw': '470 -390 440 -420 470 -390 470 -390 470 -390 470 -45000', 'RepeatPause': '0', 'RepeatSignal': '', 'Signal': '0', 'Updated': '0'}
  _get - url='http://192.168.0.123/sensors/IR'
  Connection Reset!  The device might be restarting due to a crash.
  _get - url='http://192.168.0.123/sensors/IR'
  _get - url='http://192.168.0.123/sensors/IR'
  _get - url='http://192.168.0.123/sensors/IR'
  _get - url='http://192.168.0.123/sensors/IR'
  _get - url='http://192.168.0.123/sensors/IR'
  _get - url='http://192.168.0.123/sensors/IR'
  _get - url='http://192.168.0.123/sensors/IR'
  _get - url='http://192.168.0.123/sensors/IR'
  {'IsRepeated': '0', 'Protocol': 'FF', 'Raw': '3510 -1690 470 -1260 470 -390 470 -390 470 -390 470 -45000', 'RepeatPause': '0', 'RepeatSignal': '', 'Signal': '0', 'Updated': '1630870829'}
  _get - url='http://192.168.0.123/sensors/IR'
  _get - url='http://192.168.0.123/sensors/IR'
  _get - url='http://192.168.0.123/sensors/IR'
  _get - url='http://192.168.0.123/sensors/IR'
  _get - url='http://192.168.0.123/sensors/IR'
  _get - url='http://192.168.0.123/sensors/IR'
  _get - url='http://192.168.0.123/sensors/IR'
  Connection Reset!  The device might be restarting due to a crash.
  _get - url='http://192.168.0.123/sensors/IR'
  _get - url='http://192.168.0.123/sensors/IR'
  _get - url='http://192.168.0.123/sensors/IR'
  _get - url='http://192.168.0.123/sensors/IR'
  _get - url='http://192.168.0.123/sensors/IR'
  _get - url='http://192.168.0.123/sensors/IR'
  {'IsRepeated': '0', 'Protocol': '00', 'Raw': '470 -390 470 -390 470 -390 470 -390 440 -410 470 -45000', 'RepeatPause': '0', 'RepeatSignal': '', 'Signal': '0', 'Updated': '0'}
  _get - url='http://192.168.0.123/sensors/IR'
  _get - url='http://192.168.0.123/sensors/IR'
  {'IsRepeated': '0', 'Protocol': 'FF', 'Raw': '470 -390 470 -390 470 -390 470 -390 440 -410 470 -45000', 'RepeatPause': '0', 'RepeatSignal': '', 'Signal': '0', 'Updated': '1630892222'}
  _get - url='http://192.168.0.123/sensors/IR'
  _get - url='http://192.168.0.123/sensors/IR'
  _get - url='http://192.168.0.123/sensors/IR'
  _get - url='http://192.168.0.123/sensors/IR'
  _get - url='http://192.168.0.123/sensors/IR'
  _get - url='http://192.168.0.123/sensors/IR'
  _get - url='http://192.168.0.123/sensors/IR'
  _get - url='http://192.168.0.123/sensors/IR'
  {'IsRepeated': '0', 'Protocol': 'FF', 'Raw': '470 -390 470 -390 470 -390 470 -390 440 -420 470 -45000', 'RepeatPause': '0', 'RepeatSignal': '', 'Signal': '0', 'Updated': '1630900942'}
  ...Sensor dump finished.  10 signals detected.
  ...capture complete!  You can stop triggering the IR remote.
  IR COMMANDS ARE 99% SIMILAR; LENGTH 584<=>584 IS SAME; MATCH!
  IR COMMANDS ARE 99% SIMILAR; LENGTH 584<=>584 IS SAME; MATCH!
  IR COMMANDS ARE 99% SIMILAR; LENGTH 584<=>584 IS SAME; MATCH!
  IR COMMANDS ARE 24% SIMILAR; LENGTH 584<=>144 IS DIFFERENT; NOT A MATCH
  IR COMMANDS ARE 41% SIMILAR; LENGTH 584<=>308 IS DIFFERENT; NOT A MATCH
  IR COMMANDS ARE 24% SIMILAR; LENGTH 584<=>144 IS DIFFERENT; NOT A MATCH
  IR COMMANDS ARE 99% SIMILAR; LENGTH 584<=>584 IS SAME; MATCH!
  IR COMMANDS ARE 99% SIMILAR; LENGTH 584<=>584 IS SAME; MATCH!
  IR COMMANDS ARE 99% SIMILAR; LENGTH 584<=>584 IS SAME; MATCH!
  IR COMMANDS ARE 99% SIMILAR; LENGTH 584<=>584 IS SAME; MATCH!
  IR COMMANDS ARE 99% SIMILAR; LENGTH 584<=>584 IS SAME; MATCH!
  IR COMMANDS ARE 24% SIMILAR; LENGTH 584<=>144 IS DIFFERENT; NOT A MATCH
  IR COMMANDS ARE 41% SIMILAR; LENGTH 584<=>308 IS DIFFERENT; NOT A MATCH
  IR COMMANDS ARE 24% SIMILAR; LENGTH 584<=>144 IS DIFFERENT; NOT A MATCH
  IR COMMANDS ARE 99% SIMILAR; LENGTH 584<=>584 IS SAME; MATCH!
  IR COMMANDS ARE 99% SIMILAR; LENGTH 584<=>584 IS SAME; MATCH!
  IR COMMANDS ARE 100% SIMILAR; LENGTH 584<=>584 IS SAME; MATCH!
  IR COMMANDS ARE 99% SIMILAR; LENGTH 584<=>584 IS SAME; MATCH!
  IR COMMANDS ARE 100% SIMILAR; LENGTH 584<=>584 IS SAME; MATCH!
  IR COMMANDS ARE 99% SIMILAR; LENGTH 584<=>584 IS SAME; MATCH!
  IR COMMANDS ARE 24% SIMILAR; LENGTH 584<=>144 IS DIFFERENT; NOT A MATCH
  IR COMMANDS ARE 41% SIMILAR; LENGTH 584<=>308 IS DIFFERENT; NOT A MATCH
  IR COMMANDS ARE 24% SIMILAR; LENGTH 584<=>144 IS DIFFERENT; NOT A MATCH
  IR COMMANDS ARE 99% SIMILAR; LENGTH 584<=>584 IS SAME; MATCH!
  IR COMMANDS ARE 99% SIMILAR; LENGTH 584<=>584 IS SAME; MATCH!
  IR COMMANDS ARE 99% SIMILAR; LENGTH 584<=>584 IS SAME; MATCH!
  IR COMMANDS ARE 99% SIMILAR; LENGTH 584<=>584 IS SAME; MATCH!
  IR COMMANDS ARE 100% SIMILAR; LENGTH 584<=>584 IS SAME; MATCH!
  IR COMMANDS ARE 99% SIMILAR; LENGTH 584<=>584 IS SAME; MATCH!
  IR COMMANDS ARE 24% SIMILAR; LENGTH 584<=>144 IS DIFFERENT; NOT A MATCH
  IR COMMANDS ARE 41% SIMILAR; LENGTH 584<=>308 IS DIFFERENT; NOT A MATCH
  IR COMMANDS ARE 24% SIMILAR; LENGTH 584<=>144 IS DIFFERENT; NOT A MATCH
  IR COMMANDS ARE 99% SIMILAR; LENGTH 584<=>584 IS SAME; MATCH!
  IR COMMANDS ARE 99% SIMILAR; LENGTH 584<=>584 IS SAME; MATCH!
  IR COMMANDS ARE 99% SIMILAR; LENGTH 584<=>584 IS SAME; MATCH!
  IR COMMANDS ARE 99% SIMILAR; LENGTH 584<=>584 IS SAME; MATCH!
  IR COMMANDS ARE 24% SIMILAR; LENGTH 584<=>144 IS DIFFERENT; NOT A MATCH
  IR COMMANDS ARE 41% SIMILAR; LENGTH 584<=>308 IS DIFFERENT; NOT A MATCH
  IR COMMANDS ARE 24% SIMILAR; LENGTH 584<=>144 IS DIFFERENT; NOT A MATCH
  IR COMMANDS ARE 99% SIMILAR; LENGTH 584<=>584 IS SAME; MATCH!
  IR COMMANDS ARE 99% SIMILAR; LENGTH 584<=>584 IS SAME; MATCH!
  IR COMMANDS ARE 99% SIMILAR; LENGTH 584<=>584 IS SAME; MATCH!
  IR COMMANDS ARE 99% SIMILAR; LENGTH 584<=>584 IS SAME; MATCH!
  IR COMMANDS ARE 38% SIMILAR; LENGTH 144<=>308 IS DIFFERENT; NOT A MATCH
  IR COMMANDS ARE 100% SIMILAR; LENGTH 144<=>144 IS SAME; MATCH!
  IR COMMANDS ARE 24% SIMILAR; LENGTH 584<=>144 IS DIFFERENT; NOT A MATCH
  IR COMMANDS ARE 24% SIMILAR; LENGTH 584<=>144 IS DIFFERENT; NOT A MATCH
  IR COMMANDS ARE 24% SIMILAR; LENGTH 144<=>584 IS DIFFERENT; NOT A MATCH
  IR COMMANDS ARE 24% SIMILAR; LENGTH 144<=>584 IS DIFFERENT; NOT A MATCH
  IR COMMANDS ARE 38% SIMILAR; LENGTH 308<=>144 IS DIFFERENT; NOT A MATCH
  IR COMMANDS ARE 41% SIMILAR; LENGTH 308<=>584 IS DIFFERENT; NOT A MATCH
  IR COMMANDS ARE 41% SIMILAR; LENGTH 308<=>584 IS DIFFERENT; NOT A MATCH
  IR COMMANDS ARE 24% SIMILAR; LENGTH 144<=>584 IS DIFFERENT; NOT A MATCH
  IR COMMANDS ARE 24% SIMILAR; LENGTH 144<=>584 IS DIFFERENT; NOT A MATCH
  IR COMMANDS ARE 100% SIMILAR; LENGTH 584<=>584 IS SAME; MATCH!
  IR COMMANDS ARE 99% SIMILAR; LENGTH 584<=>584 IS SAME; MATCH!
  Found 2 groups of commands.



  SUCCESS capturing command!  Command selected with 6 matches out of 10 total signals detected.
  _get - url='http://192.168.0.123/data'
  _get - url='http://192.168.0.123/data/2345'
  _get - url='http://192.168.0.123/data/3456'
  _get - url='http://192.168.0.123/data/1234'
  _get - url='http://192.168.0.123/data/4567'
  Error writing function to device; saving to auxiliary data file...
  ...Done!
  _get - url='http://192.168.0.123/data/1234'What's happening here is that the Python code is monitoring the data being captured by the LOOKin Remote's IR sensor and then processes the data to generate what it believes is the desired remote function.Running sensor dump for 300 seconds...Monitors the LOOKin Remote's IR sensor for 5 minutes or until 10 IR signals have been captured._get - url='http://192.168.0.123/sensors/IR'This is a debug message printed every time the script talks to the device.  It is currently enabled to help the user visually see that the device is or is not responding.Connection Reset!  The device might be restarting due to a crash.Indicates the communications with the LOOKin Remote failed, either from a timeout or from the connection being reset.  Usually, this is caused by the LOOKin Remote becoming unstable; long IR sequences seemed to be especially good at causing the LOOKin Remote grief.{'IsRepeated': '0', 'Protocol': 'FF', 'Raw': '470 -390 470 -390 470 -390 470 -390 470 -390 470 -45000', 'RepeatPause': '0', 'RepeatSignal': '', 'Signal': '0', 'Updated': '1630995857'}The raw IR sensor data received from the LOOKin Remote.  The length of this will vary significantly depending on the type of command/remote you're using....Sensor dump finished.  10 signals detected.&...capture complete!  You can stop triggering the IR remote.Indicates the IR sensor monitoring has concluded, either due to 300 seconds having passed or 10 IR signals found.IR COMMANDS ARE 99% SIMILAR; LENGTH 584<=>584 IS SAME; MATCH!&IR COMMANDS ARE 24% SIMILAR; LENGTH 584<=>144 IS DIFFERENT; NOT A MATCHThis is the debug output of the IR signal correlation routine.  Similar/identical IR signals are grouped together to help the script determine what is the most likely IR signal.Found 2 groups of commands.Indicates how many groupings of similar commands were found.  In this case, the Python code has determined that 2 different types of IR commands were read by the IR sensor.  Groups below a certain size (e.g. just 1 signal) will be ignored.SUCCESS capturing command!  Command selected with 6 matches out of 10 total signals detected.Indicates success/failure in identifying the IR command.10indicates the total number of commands captured, and6indicates how many signals out of those10were similar.  Ultimately, the IR command selected is the one with the largest grouping._get - url='http://192.168.0.123/data'&_get - url='http://192.168.0.123/data/1234'Debug statements from the script trying to write the function to the LOOKin Remote.Error writing function to device; saving to auxiliary data file...Indicates the writing of the function to the LOOKin Remote failed.  This is usually due to a500 Internal Server Errorbeing returned by the LOOKin Remote in response to the "Create Function" call.As indicated, if you supplied an auxiliary data file then the remote command will be stored there instead....Done!Indicates the process of storing the learned IR command has completed.Using Remote CommandsThis module can trigger remote functions both on the LOOKin Remote device and stored in an auxiliary data file:from pylookinremote import LOOKinRemote

  auxDataFilePath='./auxData.json'  #File that saved function data is in.
  dev = LOOKinRemote('192.168.0.123', auxDataFilePath)
  remoteUUID = '1234'  #ID of the IR remote on the LOOKin Remote.
  remoteFunctionName = 'myFunctionName'  #`str` name of the function to trigger.
  remote = dev.remoteFromUUID(remoteUUID)
  remote.functionTrigger(remoteFunctionName)Functions defined on the LOOKin Remote device will take precedence over the auxiliary data file.Available MethodsEverything is centered around theLOOKinRemoteclass, instantiated either byLOOKinRemote('192.168.0.123')or the class methodLOOKinRemote.findInNetwork().I strongly recommend usinghelp(LOOKinRemote)in Python and/or looking at the source code in "pylookinremote.py" for the most accurate documentation, but here is the list at the time of this writing:Classpylookinremote.LOOKinRemoteThe core class.  Each instance of this object represents a single LOOKin Remote device.The most common way to get these objects is either by:auxDataFilePath='./auxData.json'  #File that saved function data is/will-be in.
  remotes = LOOKinRemote.findInNetwork(auxDataFilePath=auxDataFilePath)  #`list` of `LOOKinRemote` objects.
  remote = remotes[0]...or by:auxDataFilePath='./auxData.json'  #File that saved function data is/will-be in.
  ipOrDNSAddr = '192.168.0.123'
  remote = remote.LOOKinRemote(ipOrDNSAddr, auxDataFilePath)  #Single `LOOKinRemote` object.Public Attributes/Methodstemp_F = LOOKinRemote.celsius2Fahrenheit(temp_C):   Static Method.  Returnstemp_Cin degrees Fahrenheit.temp_C = LOOKinRemote.fahrenheit2Celsius(temp_F):   Static Method.  Returnstemp_Fin degrees Celsius.remotes = LOOKinRemote.findInNetwork(timeout_sec=10, auxDataFilePath=None):   Class method.  Searches the network fortimeout_secseconds for available LOOKin Remote devices and returns a list ofLOOKinRemoteobjects.  Requires thatzeroconflibrary be installed.  IfauxDataFilePathis defined, a file will be opened/created there to store/retrieve IR function data.remote = LOOKinRemote('192.168.0.123', auxDataFilePath=None) :   Constructor accepting anstrIP or DNS address.  IfauxDataFilePath` is defined, a file will be opened/created there to store/retrieve IR function data.remote.api_*_DEL:   Methods that map directly to LOOKin Device APIDELcalls as defined by LOOKin:https://look-in.club/en/support/api.remote.api_*_GET:   Methods that map directly to LOOKin Device APIGETcalls as defined by LOOKin:https://look-in.club/en/support/api.remote.api_*_POST:   Methods that map directly to LOOKin Device APIPOSTcalls as defined by LOOKin:https://look-in.club/en/support/api.remote.api_*_PUT:   Methods that map directly to LOOKin Device APIPUTcalls as defined by LOOKin:https://look-in.club/en/support/api.remote.commandEventLocalRemote(uuid, functionCode, signalID=0xFF):   Triggers a "localremote" command event withfunctionCodeandsignalID.remote.commandEventNEC1(uuid, functionCode, signalID=0xFF):   Triggers an "NEC1" command event withsignal.remote.commandEventNECX(signal):   Triggers an "NECx" command event withsignal.remote.commandEventProntoHEX(signal):   Triggers a "ProntoHEX" command event.remote.commandEventRaw(signal, freqCarrier_Hz=38000):   Triggers a "raw" command event.remote.commandEvents(command):   Returns the remote's available events forcommand.remote.commandEventSaved(signalID):   Triggers a "saved" command event withsignalID.remote.commands():   Returns the remote's available command classes.remote.remoteCreate(name, irRemoteType, extra='', uuid=None):   Creates a new IR remote definition on the device.remote.remoteFromUUID(uuid):   Returns a newIRRemoteobject for the remote matchinguuid.remote.remotes():   Returns the remote's saved IR remotes.remote.remotesData():   Returns the general data for all saved remotes.remote.remotesDelete(uuids):   Deletes the IR remotesuuidsfrom the device.remote.remotesDeleteAll(*, yesIWantToDoThis=False):   Deletes all saved IR remotes from the device.remote.sensor(name):   Returns the remote's sensor information.remote.sensorDump(name, period, duration, maxSignals=None):   Polls thenamesensor fordurationseconds andperiodseconds between calls.  Terminates early ifmaxSignalshave been received.  Returns alistof data for all the non-empty captures (only "IR" sensor supported right now).remote.sensorNames():   Returns the remote's available sensors.Classpylookinremote.IRRemoteBase class for objects returned bypylookinremote.LOOKinRemote.remotes().  Users will rarely instantiate this class themselves.The most common way to get these objects is either by:irRemotes = remote.remotes()  #`list` of `IRRemote` objects....or by:uuid = '1234'
  irRemote = remote.remoteFromUUID(uuid)  #Single `IRRemote` object, or `None` if `uuid` didn't match.Public Attributes/MethodsirRemote.uuid:strUUID of the remote on the LOOKin Remote device.irRemote.name:strname of the remote on the LOOKin Remote device.irRemote.rType:   Type of the remote as an instance ofpylookinremote.IRRemote.TYPE.irRemote.updated:datetime.datetimeobject reprenting the last time the remote was modified on the LOOKinRemote device.irRemote.functions:dictmappingstrfunction names topylookinremote.IRRemoteFunctionobjects.irRemote = pylookinremote.IRRemote(lookinRemote, uuid, rootData=None, auxDataFilePath=None):   Constructor initializing the object.lookinRemoteis aLOOKinRemoteobject.uuidis thestrUUID of this remote onlookinRemote.irRemote.details():   Returns this remote's details.irRemote.delete():   Deletes this IR remote from the device.irRemote.functionCreate(irRemoteFunction):   Creates a function on the remote device using the data inirRemoteFunction.irRemoteFunctionshould be apylookinremote.IRRemoteFunctionobject.irRemote.functionDelete(functionName):   Deletes the functionfunctionNamefrom the device.irRemote.functionExists(functionName):   ReturnsTrueif a function namedfunctionNameis defined.irRemote.functionTrigger(functionName):   Triggers the functionfunctionName.  The exact behavior depends on the type of function.irRemote.functionUpdate(irRemoteFunction, upsert=True):   Updates the function definition forirRemoteFunction, apylookinremote.IRRemoteFunctionobject.  Ifupsertis true, will create the function if it doesn't currently exist.irRemote.toJSON():   Returns a JSON-compatible data structure that represents this object.irRemote.update(name=None, irRemoteType=None, extra=None):   Updates the IR remote definition foruuidon the device.Nonevalues will be unmodified.Classpylookinremote.IRRemote.TYPEEnum of possible IR Remote Types.Public Attributes/Methodspylookinremote.IRRemote.TYPE.CUSTOM:CUSTOMremote type.pylookinremote.IRRemote.TYPE.TV:TVremote type.pylookinremote.IRRemote.TYPE.MEDIA:MEDIAremote type.pylookinremote.IRRemote.TYPE.LIGHT:LIGHTremote type.pylookinremote.IRRemote.TYPE.HUMIDIFIER_DEHUMIDIFIER:HUMIDIFIER_DEHUMIDIFIERremote type.pylookinremote.IRRemote.TYPE.AIRPURIFIER:AIRPURIFIERremote type.pylookinremote.IRRemote.TYPE.ROBOVACUUMCLEANER:ROBOVACUUMCLEANERremote type.pylookinremote.IRRemote.TYPE.DATADEVICEFAN:DATADEVICEFANremote type.pylookinremote.IRRemote.TYPE.AIRCONDITIONER:AIRCONDITIONERremote type.  Remotes of this type should always be instances ofpylookinremote.ACRemote, a subclass ofpylookinremote.IRRemote.Classpylookinremote.ACRemoteSubclass ofpylookinremote.IRRemotethat provides air conditioner/heat pump functions.Obtain the same way aspylookinremote.IRRemoteobjects:irRemotes = remote.remotes()  #Any remotes with type `pylookinremote.IRRemote.TYPE.AIRCONDITIONER` will `ACRemote` objects instead of standard `IRRemote` objects.
  acRemotes = [irRemote for irRemote in irRemotes if isinstance(irRemote, pylookinremote.ACRemote]...or by:uuid = '1234'
  irRemote = remote.remoteFromUUID(uuid)  #Will be an `ACRemote` object if the target remote has the type `pylookinremote.IRRemote.TYPE.AIRCONDITIONER`.
  acRemote = irRemote if isinstance(irRemote, pylookinremote.ACRemote) else NonePublic Attributes/MethodsacRemote.operatingModeSet(operatingMode):   Tells the device to switch operating mode tooperatingMode.operatingModeshould be an instance ofpylookinremote.ACRemote.OPERATINGMODE.acRemote.tempSet(temp_C):   Tells the device to target the Celsius temperaturetemp_C.acRemote.tempSetF(temp_F):   Tells the device to target the Fahrenheit temperaturetemp_F.acRemote.fanSpeedModeSet(fanSpeedMode):   Tells the device to usefanSpeedMode.fanSpeedModeshould be an instance ofpylookinremote.ACRemote.FANSPEEDMODE.acRemote.swingModeSet(swingMode):   Tells the device to useswingMode.swingModeshould be an instance ofpylookinremote.ACRemote.SWINGMODE.acRemote.statusGet(refresh=False):   Returns the current status of the device.  Will return the cached state unlessrefreshisTrue.acRemote.statusRefresh():   Requests the current status from the device.acRemote.statusSet(status):   Modifies the device's status to matchstatus.statusshould be an instance ofpylookinremote.ACRemote.Status.Classpylookinremote.ACRemote.OPERATINGMODEEnum of available air conditioner/heat pump operating modes.Public Attributes/Methodspylookinremote.ACRemote.OPERATINGMODE.OFF:   Air conditioner is off.pylookinremote.ACRemote.OPERATINGMODE.AUTO:   Air conditioner is on auto.pylookinremote.ACRemote.OPERATINGMODE.COOL:   Air conditioner is cooling.pylookinremote.ACRemote.OPERATINGMODE.HEAT:   Air conditioner is heating.Classpylookinremote.ACRemote.FANSPEEDMODEEnum of available air conditioner/heat pump fan speed modes.Public Attributes/Methodspylookinremote.ACRemote.FANSPEEDMODE.MINIMUM:   Air conditiner fan speed is at minimum speed.pylookinremote.ACRemote.FANSPEEDMODE.MEDIUM:   Air conditiner fan speed is at a moderate speed.pylookinremote.ACRemote.FANSPEEDMODE.MAXIMUM:   Air conditiner fan speed is at maximum speed.pylookinremote.ACRemote.FANSPEEDMODE.AUTO:   Air conditioner fan speed is automatic.Classpylookinremote.ACRemote.SWINGMODEEnum of available air conditioner/heat pump diffuser swing modes.Public Attributes/MethodsNo modes appear to be working right now (at least for my devices), so all are marked asUNDEFINED.Classpylookinremote.ACRemote.StatusClass representing a status of the air conditioner/heat pump device.This is typically obtained by:acStatus = acRemote.statusGet()Public Attributes/MethodsacStatus.operatingMode:   Instance ofpylookinremote.ACRemote.OPERATINGMODE.acStatus.tempTarget_C:   Target temperature in degrees Celsius.acStatus.tempTarget_F:   Target temperature in degrees Fahrenheit.acStatus.fanSpeedMode:   Instance ofpylookinremote.ACRemote.FANSPEEDMODE.acStatus.swingMode:   Instance ofpylookinremote.ACRemote.SWINGMODE.acStatus = pylookinremote.ACRemote.Status(operatingMode, tempTarget_C, fanSpeedMode, swingMode):   Constructor.acStatus = pylookinremote.ACRemote.Status.fromStatusBytes(statusBytes):   Class method.  Creates an instance of this class using the data contained instatusBytes.acStatus.operatingModeSet(operatingMode):   Sets this object's operating mode tooperatingMode.acStatus.tempTargetSet(tempTarget_C):   Sets this object's target temperature totempTarget_C(Celsius).acStatus.tempTargetSet_F(tempTarget_F):   Sets this object's target temperature totempTarget_F(Fahrenheit).acStatus.toStatusBytes():   Returns the 16-bit integer with the appropriate status bytes for this object.acStatus.fanSpeedModeSet(fanSpeedMode):   Sets this object's fan speed tofanSpeedMode.acStatus.swingModeSet(swingMode):   Sets this object's swing mode toswingMode.Classpylookinremote.IRRemoteFunctionClass representing a function of an IR Remote.This is typically obtained by:irFunctions = irRemote.functions()
  irFunction = irFunctions['myFunctionName']Public Attributes/MethodsirFunction.name:strname of the function.irFunction.functionType:   Type of the function as an instance ofpylookinremote.IRRemoteFunction.TYPE.irFunction.irCommands:tupleofpylookinremote.IRRemoteCommandobjects.Noneindicates the commands are stored on the LOOKin Remote device.irFunction = pylookinremote.IRRemoteFunction.fromJSON(jsonData):   Static method.  Creates a newIRRemoteFunctionobject from the givenjsonData.irFunction = pylookinremote.IRRemoteFunction.fromIRSensor(lookinRemote, functionName, functionType=TYPE.SINGLE):   Static method.  Creates/"Learns" a newIRRemoteFunctionobject from IR sequences detected by the givenlookinRemote's IR sensor.  This is a function that requires guided user interaction with the LOOKin Remote device.irFunction = pylookinremote.IRRemoteFunction(functionName, irRemoteCommands, functionType=TYPE.SINGLE):   Constructor.functionNameshould be astrname for the function.irRemoteCommandsshould be either an iterable ofIRRemoteCommandobjects or a singleIRRemoteCommandobject.functionTypeshould be a value fromIRRemoteFunction.TYPE.irFunction.toJSON():   Returns this object serialized into a JSON-compatible data structure.irFunction.trigger(lookinRemote):   Triggers this function on the givenlookinRemote.Classpylookinremote.IRRemoteCommand.TYPEEnum of possible IR Remote Function types.Public Attributes/Methodspylookinremote.IRRemoteFunction.TYPE.SINGLE:SINGLEfunction type.pylookinremote.IRRemoteFunction.TYPE.TOGGLE:TOGGLEremote type.Classpylookinremote.IRRemoteCommandBase class for IR Remote Commands.  This is not useful until it is subclassed.This is typically obtained by:irFunctions = irRemote.functions()
  irFunction = irFunctions['myFunctionName']
  irCommands = irFunction.irCommands
  irCommand = irCommands[0]...or by direct construction of one of its subclasses:irCommandRaw = pylookinremote.IRRemoteCommandRaw('470 -390 470 -390 470 -390 470 -390 470 -390 470 -45000')Public Attributes/MethodsirCommand.typeName:strname of the command type.irCommand = pylookinremote.IRRemoteCommand.fromJSON(jsonData):   Static method.  Creates a newIRRemoteCommandobject--or one of its appropriate subclasses--from the givenjsonData.irCommand = pylookinremote.IRRemoteCommand.fromIRSensorData(jsonSensorData):   Static method.  Creates a newIRRemoteCommandobject--or one of its appropriate subclasses--from the givenjsonSensorData.jsonSensorDatashould be as it was returned byLOOKinRemote.sensor('IR').  Only "raw" commands are currently supported.irCommand = pylookinremote.IRRemoteCommand(typeName):   Constructor.typeNameshould be astrname for the command type (e.g. "raw").irCommand.toJSON():   Returns a JSON-compatible data structure that represents this object.irCommand.trigger(lookinRemote):   Triggers this command on the givenlookinRemote.Classpylookinremote.IRRemoteCommandUndefinedRepresents an undefined-type remote command.Public Attributes/MethodsirCommand.data:   Pythonobjectof relevant data.irCommand = pylookinremote.IRRemoteCommandUndefined(typeName, data):   Constructor.typeNameshould be astrname for the command type (e.g. "raw"), anddatacan be anything.irCommand.toJSON():   Returns a JSON-compatible data structure that represents this object.irCommand.trigger(lookinRemote):   Triggers this command on the givenlookinRemote.Classpylookinremote.IRRemoteCommandRawRepresents a raw-type remote command sequence.Public Attributes/MethodsirCommandRaw = pylookinremote.IRRemoteCommandRaw(sequence, freqCarrier_Hz=38000):   Constructor.sequenceshould be an IR command sequence either as astror iterable ofints.irCommandRaw.isSimilar(rhs):   ReturnsTrueifrhsis similar to this object;Falseotherwise.len(irCommandRaw):   Returns the length of the stored IR sequence.irCommandRaw.toJSON():   Returns a JSON-compatible data structure that represents this object.irCommandRaw.toLOOKinRemoteAPIJSON():   Returns a JSON-compatible data structure that represents this object appropriately for the LOOKin Device API.irCommandRaw.trigger(lookinRemote):   Triggers this command on the givenlookinRemote.