def genVehicleList(self, filter, valuesDict, typeId, devID): device = indigo.devices[devID] try: connection = jlrpy.Connection( self.pluginPrefs['InControlEmail'], self.pluginPrefs['InControlPassword']) except: self.errorLog( "Error connecting to JLR Servers - Check Email and Password") self.debugLog("Successfully Connected to JLR Servers") #error is HTTPError: HTTP Error 403: Forbidden # Retrieve the list of vehicles from JLRpy and write out the Vehicle Identification numbers to the event log so they can match to the right car # Only necessary if multiple cars added to the same account vehiclelist = connection.vehicles vin = [] for item in vehiclelist: vin.append(item['vin']) # Dump to event log the number of vehicles associated with the account indigo.server.log( str(len(vehiclelist)) + " Vehicle(s) Available for InControl account " + self.pluginPrefs['InControlEmail']) self.debugLog(vehiclelist) self.debugLog(vin) vid = [] for index, item in enumerate(vehiclelist): self.debugLog(index) vid.append(str(index + 1)) # Output to event log the numbers for the menu mapped to the VIN number by account indigo.server.log("For menu number " + str(index + 1) + " VIN is " + vehiclelist[index]['vin']) indigo.server.log( "VIN Can be found on the assistance tab of the InControl App") return vid
def honkAndBlink(self, pluginAction, dev): self.debugLog(dev) c = jlrpy.Connection(self.pluginPrefs['InControlEmail'], self.pluginPrefs['InControlPassword']) #The Car ID from the device defintion maps to the relevant car if multiple cars on one account #Adjust for index starting at 0 vehicle_num = int(dev.pluginProps['CarID']) - 1 v = c.vehicles[vehicle_num] v.honk_blink() self.debugLog("Honked and Blinked") return ()
def stopClimate(self, pluginAction, dev): self.debugLog(dev) c = jlrpy.Connection(self.pluginPrefs['InControlEmail'], self.pluginPrefs['InControlPassword']) #The Car ID from the device defintion maps to the relevant car if multiple cars on one account #Adjust for index starting at 0 vehicle_num = int(dev.pluginProps['CarID']) - 1 v = c.vehicles[vehicle_num] v.preconditioning_stop() self.debugLog("Climate Stopped") return ()
def validateDeviceConfigUi(self, valuesDict, typeId, device): c = jlrpy.Connection(self.pluginPrefs['InControlEmail'], self.pluginPrefs['InControlPassword']) #The Car ID from the device defintion maps to the relevant car if multiple cars on one account #Adjust for index starting at 0 self.debugLog(valuesDict) vehicle_num = int(valuesDict['CarID']) - 1 v = c.vehicles[vehicle_num] adjustedtemp = valuesDict['climateTemp'] + "0" valuesDict['address'] = v['vin'] valuesDict['adjustedclimateTemp'] = adjustedtemp self.debugLog(valuesDict) return (True, valuesDict)
def main(): #Get login info from commandline email = sys.argv[1] password = sys.argv[2] #Create connection and get the ipace connect = jp.Connection(email=email, password=password) v = connect.vehicles[0] #do stuff stat = v.get_status() #pprint.pprint(stat) pprint.pprint(v.get_position())
def __init__(self, hass, config): self._hass = hass self.config = config self.vehicle = None self.connection = None self.attributes = None self.status = None self.wakeup = None self.position = None self.user_info = None self.timer_handle = None self.health_timer_handle = None self.pin = self.config[DOMAIN].get(CONF_PIN) self.update_interval = self.config[DOMAIN].get(CONF_SCAN_INTERVAL) * 60 self.health_update_interval = ( self.config[DOMAIN].get(CONF_HEALTH_UPDATE_INTERVAL) * 60) _LOGGER.debug("Creating connection to JLR InControl API") self.connection = jlrpy.Connection( email=self.config[DOMAIN].get(CONF_USERNAME), password=self.config[DOMAIN].get(CONF_PASSWORD), ) # Get one time info self.vehicle = self.connection.vehicles[0] self.attributes = self.vehicle.get_attributes() # Add one time dump of attr and status data for debugging if self.config[DOMAIN].get(CONF_DEBUG_DATA): _LOGGER.debug("ATTRIBUTE DATA - {}".format(self.attributes)) status = self.vehicle.get_status() self.status = { d["key"]: d["value"] for d in status["vehicleStatus"] } _LOGGER.debug("STATUS DATA - {}".format(self.status)) # Schedule health update and repeat interval if self.health_update_interval > 0: _LOGGER.debug( "Scheduling vehicle health update on {} minute interval". format(int(self.health_update_interval / 60))) self.do_health_update() else: _LOGGER.debug( "Scheduled vehicle health update is disabled. Add to configuration.yaml to enable." ) _LOGGER.debug( "Scheduling update from InControl servers on {} minute interval". format(int(self.update_interval / 60)))
def setupConnectionToVehicle(): logger.info("Reading credentials from file") try: config = configparser.ConfigParser() config.read(os.path.expanduser('~') + "/.ipace.conf") email = config.get('credentials', 'email') password = config.get('credentials', 'password') except configparser.Error: exit("Error reading configfile!") c = jlrpy.Connection(email, password) v = c.vehicles[0] return(v)
def connect(): c = jlrpy.Connection('', '') v = c.vehicles[0] trips = v.get_trips(2000)['trips'] counter = 0 # for trip in trips: # print(f"Processing trip {counter} of {len(trips)}") # try: # trip['waypoints'] = v.get_trip(trip['id'])['waypoints'] # with open(f"trips/{trip['id']}.json", "w") as f: # f.write(json.dumps(trip, indent=2)) # except: # print(f"Error processing trip: {trip['id']}") # counter += 1 print(len(trips))
def get_jlr_connection(): global jlr_connection logger.debug("Checking for existing connection") if jlr_connection is not None: logger.debug("Connection found. Checking expiry") now_ts = int(datetime.datetime.now().timestamp()) if now_ts > jlr_connection.expiration: jlr_connection = None else: logger.info("No existing 'jlr_connection' available") if jlr_connection is None: logger.info("Instantiating new connection to JLR") jlr_connection = jlrpy.Connection(JLR_USER, JLR_PW, JLR_DEVICE_ID) else: logger.debug("Connecton exists....") return jlr_connection
def handler(event, context): email = os.getenv('JLR_EMAIL', None) password = os.getenv('JLR_PASS', None) c = jlrpy.Connection(email, password) v = c.vehicles[0] trips = v.get_trips(10)['trips'] for trip in trips: blob = storage.Blob(bucket=bucket, name=f"{trip['id']}.json") already_added = blob.exists() print(f"Trip id {trip['id']}. Already added: {already_added}") if not already_added: print('Loading waypoint data for trip') try: trip['waypoints'] = v.get_trip(trip['id'])['waypoints'] fname = f"{trip['id']}.json" trip_string = json.dumps(trip, indent=2) print(f"Writing to blob {fname}") blob.upload_from_string(trip_string) except Exception as e: print(f"Error processing trip: {trip['id']}") print(e)
def get_data(): epoch_time = int(time.time()) if verify_ssl == "True": ssl_verify = True else: ssl_verify = False # Authenticate using the username and password c = jlrpy.Connection(username, password) v = c.vehicles[0] user_info = c.get_user_info() status = v.get_status() healthstatus = v.get_health_status() status = {d['key']: d['value'] for d in v.get_status()['vehicleStatus']} position = v.get_position() json_status = status json_health = healthstatus json_position = dict() for k in position['position']: json_position['position-' + k] = position['position'][k] fields = dict() fields.update(json_health) fields.update(json_status) fields.update(json_position) json_out = [{ "measurement": "jlrpy-out", "tags": { "vechicle": "ipace", "region": "eu" }, "time": datetime.now(), "fields": fields }] return json_out
username = config.get('jlrpy', 'email') password = config.get('jlrpy', 'password') url = config.get('splunk', 'url') verify_ssl = config.get('jlrpy', 'insecure_ssl') token = config.get('splunk', 'token') index = config.get('splunk', 'index') epoch_time = int(time.time()) if verify_ssl == "True": ssl_verify = True else: ssl_verify = False # Authenticate using the username and password c = jlrpy.Connection(username, password) v = c.vehicles[0] user_info = c.get_user_info() status = v.get_status() healthstatus = v.get_health_status() status = {d['key']: d['value'] for d in v.get_status()['vehicleStatus']} # Assigning a bunch of variables. # Door position front_left_door_position = status['DOOR_FRONT_LEFT_POSITION'] front_right_door_position = status['DOOR_FRONT_RIGHT_POSITION'] rear_left_door_position = status['DOOR_REAR_LEFT_POSITION'] rear_right_door_position = status['DOOR_REAR_RIGHT_POSITION'] bonnet_position = status['DOOR_ENGINE_HOOD_POSITION']
def setup(hass, config): """Set up the jlrpy component.""" username = config[DOMAIN][CONF_USERNAME] password = config[DOMAIN][CONF_PASSWORD] state = hass.data[DATA_KEY] = JLRData(hass, config) interval = config[DOMAIN][CONF_SCAN_INTERVAL] try: connection = jlrpy.Connection(username, password) except urllib.error.HTTPError: _LOGGER.error("Could not connect to JLR. Please check your credentials") return False vehicles = [] for vehicle in connection.vehicles: vehicle.info = vehicle.get_status() vehicles.append(vehicle) def discover_vehicle(vehicle): state.entities[vehicle.vin] = [] for attr, (component, *_) in RESOURCES.items(): hass.helpers.discovery.load_platform( component, DOMAIN, (vehicle.vin, attr), config ) def update_vehicle(vehicle): """Update information on vehicle.""" _LOGGER.info("Pulling info from JLR") state.vehicles[vehicle.vin] = vehicle if vehicle.vin not in state.entities: discover_vehicle(vehicle) # # for entity in state.entities[vehicle.vin]: # entity.schedule_update_ha_state() # # dispatcher_send(hass, SIGNAL_VEHICLE_SEEN, vehicle) # # def update(now): # """Update status from the online service.""" # try: # for vehicle in vehicles: # update_vehicle(vehicle) # return True # except urllib.error.HTTPError: # _LOGGER.error("Could not update vehicle status") # return False # finally: # track_point_in_utc_time(hass, update, # utcnow() + interval) # # return update(utcnow()) try: for vehicle in vehicles: update_vehicle(vehicle) # return True except urllib.error.HTTPError: _LOGGER.error("Could not update vehicle status") # return False state.update(now=None) track_time_interval(hass, state.update, interval) return True
min_soc = 20 # SET MIN SOC LEVEL HERE def check_soc(): """Retrieve vehicle status and stop or start charging if current charging level matches or exceeds specified max/min level and the vehicle is currently charging. """ threading.Timer(60.0, check_soc).start() # Called every minute status = v.get_status()['vehicleStatus'] # Get current soc current_soc = int(status[38].get('value')) # Get current charging state charging_state = status[44] if current_soc >= max_soc and charging_state is "CHARGING": # Stop charging if we are currently charging v.charging_stop() elif current_soc < min_soc and charging_state is "NOT CHARGING": # Start charging v.charging_start() c = jlrpy.Connection('*****@*****.**', 'password') v = c.vehicles[0] print("[*] Enforcing max soc of %d%%" % max_soc) print("[*] Enforcing min soc of %d%%" % min_soc) check_soc()
def validatePrefsConfigUi(self, valuesDict): # if invalid_email(valuesDict['InControlEmail']): # self.errorLog("Invalid email address for JLR InControl") # errorsDict = indigo.Dict() # errorsDict['InControlEmail'] = "Invalid email address for JLR InControl" # return (False, valuesDict, errorsDict) if not (valuesDict['InControlPassword']): self.errorLog("Password Cannot Be Empty") errorsDict = indigo.Dict() errorsDict['InControlPassword'] = "******" return (False, valuesDict, errorsDict) if not (valuesDict['InControlPIN']): self.errorLog("PIN Cannot Be Empty") errorsDict = indigo.Dict() errorsDict['InControlPIN'] = "PIN Cannot Be Empty" return (False, valuesDict, errorsDict) try: timeoutint = float(valuesDict['requeststimeout']) except: self.errorLog( "Invalid entry for JLR API Timeout - must be a number") errorsDict = indigo.Dict() errorsDict[ 'requeststimeout'] = "Invalid entry for JLR API Timeout - must be a number" return (False, valuesDict, errorsDict) try: pollingfreq = int(valuesDict['pollingFrequency']) except: self.errorLog( "Invalid entry for JLR Polling Frequency - must be a whole number greater than 0" ) errorsDict = indigo.Dict() errorsDict[ 'pollingFrequency'] = "Invalid entry for JLR Polling Frequency - must be a whole number greater than 0" return (False, valuesDict, errorsDict) if int(valuesDict['pollingFrequency']) == 0: self.errorLog( "Invalid entry for JLR Polling Frequency - must be greater than 0" ) errorsDict = indigo.Dict() errorsDict[ 'pollingFrequency'] = "Invalid entry for JLR Polling Frequency - must be a whole number greater than 0" return (False, valuesDict, errorsDict) if int(valuesDict['requeststimeout']) == 0: self.errorLog( "Invalid entry for JLR Requests Timeout - must be greater than 0" ) errorsDict = indigo.Dict() errorsDict[ 'requeststimeout'] = "Invalid entry for JLR Requests Timeout - must be greater than 0" return (False, valuesDict, errorsDict) try: connection = jlrpy.Connection(valuesDict['InControlEmail'], valuesDict['InControlPassword']) except: self.errorLog( "Error connecting to JLR Servers - Check Email and Password") errorsDict = indigo.Dict() errorsDict[ 'InControlAccountEmail'] = "Invalid email address for JLR InControl" errorsDict['InControlPassword'] = "******" return (False, valuesDict, errorsDict) # error is HTTPError: HTTP Error 403: Forbidden #Otherwise we are good, log details for debugging self.debugLog("Successfully Connected to JLR Servers") self.debugLog( str(len(connection.vehicles)) + " Vehicle Available for account " + valuesDict['InControlAccountEmail']) self.debugLog(connection.vehicles) return (True, valuesDict)
def update(self, device): try: c = jlrpy.Connection(self.pluginPrefs['InControlEmail'], self.pluginPrefs['InControlPassword']) #The Car ID from the device defintion maps to the relevant car if multiple cars on one account #Adjust for index starting at 0 except: indigo.server.log("Failed to Contact JLR In Control Servers") return () vehicle_num = int(device.pluginProps['CarID']) - 1 v = c.vehicles[vehicle_num] device.updateStateOnServer('deviceIsOnline', value=True, uiValue="Starting") user_info = c.get_user_info() status = v.get_status() attributes = v.get_attributes() location = v.get_position() revgeocode = c.reverse_geocode(location['position']['latitude'], location['position']['longitude']) self.debugLog("Updating device: " + device.name) #states = [] #states.append({ 'key' : "address", 'value' : v['vin']}) device_states = [] # Update Vehicle Status for d in v.get_status()['vehicleStatus']: if d['key'] == 'EV_STATE_OF_CHARGE': device_states.append({ 'key': d['key'], 'value': d['value'], 'uiValue': (d['value'] + '%') }) elif d['key'] == "EV_CHARGING_RATE_SOC_PER_HOUR": device_states.append({ 'key': d['key'], 'value': d['value'], 'uiValue': (d['value'] + '%') }) elif d['key'] == "EV_MINUTES_TO_FULLY_CHARGED": hours = '{:02d}:{:02d}m'.format(*divmod(int(d['value']), 60)) device_states.append({ 'key': d['key'], 'value': d['value'], 'uiValue': hours }) elif d['key'] == "EV_CHARGING_STATUS": if d['value'] == "No Message": uicharge = "Not Connected" else: uicharge = d['value'] device_states.append({ 'key': d['key'], 'value': d['value'], 'uiValue': uicharge }) elif d['key'] == "THEFT_ALARM_STATUS": if d['value'] == "ALARM_ARMED": uialarm = "Armed" elif d['value'] == "ALARM_OFF": uialarm = "Not Armed" else: uialarm = d['value'] device_states.append({ 'key': d['key'], 'value': d['value'], 'uiValue': uialarm }) elif d['key'] == "EV_RANGE_VSC_REVISED_HV_BATT_ENERGYx100": device_states.append({ 'key': d['key'], 'value': d['value'], 'uiValue': (d['value'] + ' kWh') }) elif "TYRE_PRESSURE" in d['key']: if self.pluginPrefs['pressureunit'] == "Bar": convertedpressure = round(float(d['value']) * kpaInBar, 1) uipressure = str(convertedpressure) + " Bar" else: convertedpressure = round(float(d['value']) * kpaInPSI, 1) uipressure = str(convertedpressure) + " Psi" device_states.append({ 'key': d['key'], 'value': d['value'], 'uiValue': uipressure }) elif d['key'] == "DOOR_IS_ALL_DOORS_LOCKED": if d['value']: uilock = "Locked" else: uilock = "Unlocked" device_states.append({ 'key': d['key'], 'value': d['value'], 'uiValue': uilock }) else: device_states.append({'key': d['key'], 'value': d['value']}) device_states.append({ 'key': 'modelYear', 'value': attributes['modelYear'] }) device_states.append({ 'key': 'vehicleBrand', 'value': attributes['vehicleBrand'] }) device_states.append({ 'key': 'fuelType', 'value': attributes['fuelType'] }) device_states.append({ 'key': 'vehicleType', 'value': attributes['vehicleType'] }) device_states.append({ 'key': 'nickname', 'value': attributes['nickname'] }) device_states.append({ 'key': 'exteriorColorName', 'value': attributes['exteriorColorName'] }) device_states.append({ 'key': 'registrationNumber', 'value': attributes['registrationNumber'] }) device_states.append({ 'key': 'bodyType', 'value': attributes['bodyType'] }) device_states.append({ 'key': 'longitude', 'value': location['position']['longitude'] }) device_states.append({ 'key': 'latitude', 'value': location['position']['latitude'] }) device_states.append({ 'key': 'speed', 'value': location['position']['speed'] }) device_states.append({ 'key': 'heading', 'value': location['position']['heading'] }) device_states.append({ 'key': 'geoaddress', 'value': revgeocode['formattedAddress'] }) #self.debugLog(device_states) self.debugLog("States Updated - Generating Map") baseurl = "https://www.mapquestapi.com/staticmap/v5/map?locations=" locationsection = str(location['position']['latitude']) + "," + str( location['position']['longitude']) sizeandapikey = "&size=@2x&key=" + self.pluginPrefs['mapAPIkey'] mapurl = baseurl + locationsection + sizeandapikey #url = "https://www.mapquestapi.com/staticmap/v5/map?locations="+str(location['position']['latitude'])+","+str(location['position']['longitude'])+"&size=@2x&key="+self.pluginPrefs['mapAPIkey'] imagepath = "{}/IndigoWebServer/images/controls/static/carlocation{}.jpg".format( indigo.server.getInstallFolderPath(), str(vehicle_num + 1)) self.debugLog(imagepath) if self.pluginPrefs['useMapAPI']: try: r = requests.get(mapurl, timeout=0.5) if r.status_code == 200: with open(imagepath, 'wb') as f: f.write(r.content) self.debugLog("Writing Car Location Image") except: indigo.server.log("Error writing Car Location Map Image") update_time = t.strftime("%m/%d/%Y at %H:%M") device_states.append({ 'key': 'deviceLastUpdated', 'value': update_time }) #device.updateStateOnServer('deviceLastUpdated', value=update_time) #device.updateStateOnServer('deviceTimestamp', value=t.time()) device_states.append({'key': 'deviceTimestamp', 'value': t.time()}) device_states.append({ 'key': 'deviceIsOnline', 'value': True, 'uiValue': "Online" }) device.updateStatesOnServer(device_states) #device.updateStateOnServer('deviceIsOnline', value=True, uiValue="Online") self.debugLog("Done Updating States and Map") indigo.server.log("Upating States & Map Complete") return ()
def actionControlDevice(self, action, dev): ###### TURN ON Timed Climate ###### if action.deviceAction == indigo.kDeviceAction.TurnOn: jsondata = json.dumps({"on": True}) try: c = jlrpy.Connection(self.pluginPrefs['InControlEmail'], self.pluginPrefs['InControlPassword']) #The Car ID from the device defintion maps to the relevant car if multiple cars on one account #Adjust for index starting at 0 vehicle_num = int(dev.pluginProps['CarID']) - 1 v = c.vehicles[vehicle_num] v.preconditioning_start(dev.pluginProps['adjustedclimateTemp']) self.debugLog("Climate Started at " + dev.pluginProps['adjustedclimateTemp']) sendSuccess = True except: sendSuccess = False if sendSuccess: # If success then log that the command was successfully sent. indigo.server.log(u"Turned Timed Climate \"%s\" %s" % (dev.name, "on")) # And then tell the Indigo Server to update the state. dev.updateStateOnServer("onOffState", True) else: # Else log failure but do NOT update state on Indigo Server. indigo.server.log( u"Turning Timed Climate \"%s\" to %s failed" % (dev.name, "on"), isError=True) ###### TURN OFF Timed Climate ###### elif action.deviceAction == indigo.kDeviceAction.TurnOff: # Turn WLED off jsondata = json.dumps({"on": False}) try: c = jlrpy.Connection(self.pluginPrefs['InControlEmail'], self.pluginPrefs['InControlPassword']) #The Car ID from the device defintion maps to the relevant car if multiple cars on one account #Adjust for index starting at 0 vehicle_num = int(dev.pluginProps['CarID']) - 1 v = c.vehicles[vehicle_num] v.preconditioning_stop() self.debugLog("Climate Stopped") sendSuccess = True except: sendSuccess = False if sendSuccess: # If success then log that the command was successfully sent. indigo.server.log(u"sent \"%s\" %s" % (dev.name, "off")) # And then tell the Indigo Server to update the state: dev.updateStateOnServer("onOffState", False) else: # Else log failure but do NOT update state on Indigo Server. indigo.server.log(u"send \"%s\" %s failed" % (dev.name, "off"), isError=True) ###### TOGGLE ###### elif action.deviceAction == indigo.kDeviceAction.Toggle: # Toggle the WLED self.debugLog("Device for Timed Climate does not support toggle")