Carwings API?

My Nissan Leaf Forum

Help Support My Nissan Leaf Forum:

This site may earn a commission from merchant affiliate links, including eBay, Amazon, and others.
drees said:
richard said:
UhClem said:
The iPhone app uses a simple RESTful web service, so there's hope :)

Do you have any details on this?
Might have to get the packet sniffer out. :)

That's sort of what I'm suspecting. Took a look at the Carwings login page and whatever it's doing for authentication looks a bit daunting. Then again, I don't have my account yet.
 
I'm willing to bet it looks like this:

iPhone App->Carwings REST web service->AT&T SMSC Integration (or aggregator??)->AT&T Network->Leaf

So http between the app and Carwings but sms messages between Carwings and the Leaf. (we know it's 'messaging-based', just not sure what protocol)
 
sdbonez said:
I'm willing to bet it looks like this:

iPhone App->Carwings REST web service->AT&T SMSC Integration (or aggregator??)->AT&T Network->Leaf

So http between the app and Carwings but sms messages between Carwings and the Leaf. (we know it's 'messaging-based', just not sure what protocol)

So does anyone know the URL of the web service?
 
richard said:
Someone with httpfox want to analyze what goes on in an exchange?
httpfox won't help with that web service because the client is an iOS app :)

I have a proxy set up here that can capture the exchange between an iOS device and the Carwings smartphone web service. Unfortunately, I can't get any farther than the initial login exchange because Carwings isn't enabled on my account yet. I just ordered this month :(

If anyone with a car and a WiFi iPhone is willing to temporarily set up their iPhone to use my proxy and run through the functions on the iPhone Leaf app (get a status update, turn charging on and off, and so on), I'll publish the results. PM me for details :D

FYI, the login exchange is an https: POST. Request:
Code:
POST https://nissan-na-smartphone-biz.viaaq.com:443/aqPortal/smartphoneProxy/userService HTTP/1.1
Host: nissan-na-smartphone-biz.viaaq.com
User-Agent: NissanLEAF/1.16 CFNetwork/485.12.7 Darwin/10.4.0
Content-Length: 1192
Content-Type: text/xml; charset=utf-8
Accept: */*
Accept-Language: en-us
Accept-Encoding: gzip, deflate
Connection: keep-alive
Proxy-Connection: keep-alive
X-Forwarded-For: *redacted*

<?xml version="1.0"?>
<ns2:SmartphoneLoginWithAdditionalOperationRequest xmlns:ns4="urn:com:hitachi:gdc:type:report:v1" xmlns:ns7="urn:com:airbiquity:smartphone.vehicleservice:v1" xmlns:ns3="http://www.nissanusa.com/owners/schemas/api/0" xmlns:ns5="urn:com:airbiquity:smartphone.reportservice:v1" xmlns:ns2="urn:com:airbiquity:smartphone.userservices:v1" xmlns:ns6="urn:com:hitachi:gdc:type:vehicle:v1">
  <SmartphoneLoginInfo>
    <UserLoginInfo>
      <userId>*redacted*</userId>
      <userPassword>*redacted*</userPassword>
    </UserLoginInfo>
    <DeviceToken>DUMMY1294273215.34918690</DeviceToken>
    <UUID>*redacted - phone's UDID*</UUID>
    <Locale>US</Locale>
    <AppVersion>1.16</AppVersion>
    <SmartphoneType>IPHONE</SmartphoneType>
  </SmartphoneLoginInfo>
  <SmartphoneOperationType>SmartphoneGetPreferencesRequest</SmartphoneOperationType>
  <SmartphoneOperationType>SmartphoneLatestBatteryStatusRequest</SmartphoneOperationType>
  <SmartphoneOperationType>SmartphoneLatestACStatusRequest</SmartphoneOperationType>
  <SmartphoneOperationType>SmartphoneGetScheduledACRemoteRequest</SmartphoneOperationType>
</ns2:SmartphoneLoginWithAdditionalOperationRequest>
Response:
Code:
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
X-Powered-By: Servlet 2.4; JBoss-4.3.0.GA (build: SVNTag=JBPAPP_4_3_0_GA date=200801031548)/Tomcat-5.5
Content-Type: text/xml, charset=UTF-8
Content-Length: 465
Date: Fri, 14 Jan 2011 16:55:33 GMT
Set-Cookie: BIGipServernissan-na-smartphone-biz-POOL=1192559882.20480.0000; path=/

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ns7:SmartphoneErrorType xmlns:ns4="urn:com:airbiquity:smartphone.reportservice:v1" xmlns:ns7="urn:com:airbiquity:smartphone.common:v1" xmlns:ns3="urn:com:hitachi:gdc:type:report:v1" xmlns:ns5="urn:com:hitachi:gdc:type:vehicle:v1" xmlns:ns2="urn:com:airbiquity:smartphone.userservices:v1" xmlns:ns6="urn:com:airbiquity:smartphone.vehicleservice:v1">
    <ErrorCode>9002</ErrorCode>
</ns7:SmartphoneErrorType>
By the way, the App displays "No vehicles associated with this account. Please correct this at the owner's portal" when I try to log in.
 
I just tried the same thing. Here's an example of a successful response to a login:

Code:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ns2:SmartphoneLoginWithAdditionalOperationResponse xmlns:ns4="urn:com:airbiquity:smartphone.reportservice:v1" xmlns:ns7="urn:com:airbiquity:smartphone.common:v1" xmlns:ns3="urn:com:hitachi:gdc:type:report:v1" xmlns:ns5="urn:com:hitachi:gdc:type:vehicle:v1" xmlns:ns2="urn:com:airbiquity:smartphone.userservices:v1" xmlns:ns6="urn:com:airbiquity:smartphone.vehicleservice:v1">
    <SmartphoneUserInfoType>
        <VehicleInfo>
            <Vin>**redacted**</Vin>
        </VehicleInfo>
        <Nickname>leaf</Nickname>
    </SmartphoneUserInfoType>
    <ns4:SmartphoneLatestBatteryStatusResponse>
        <SmartphoneBatteryStatusResponseType>
            <ns3:BatteryStatusRecords>
                <ns3:OperationResult>START</ns3:OperationResult>
                <ns3:OperationDateAndTime>2011-08-20T04:20:59.0</ns3:OperationDateAndTime>
                <ns3:BatteryStatus>
                    <ns3:BatteryChargingStatus>NORMAL_CHARGING</ns3:BatteryChargingStatus>
                    <ns3:BatteryCapacity>12</ns3:BatteryCapacity>
                    <ns3:BatteryRemainingAmount>8</ns3:BatteryRemainingAmount>
                </ns3:BatteryStatus>
                <ns3:PluginState>CONNECTED</ns3:PluginState>
                <ns3:CruisingRangeAcOn>90624</ns3:CruisingRangeAcOn>
                <ns3:CruisingRangeAcOff>104448</ns3:CruisingRangeAcOff>
                <ns3:TimeRequiredToFull>
                    <ns3:HourRequiredToFull>6</ns3:HourRequiredToFull>
                    <ns3:MinutesRequiredToFull>0</ns3:MinutesRequiredToFull>
                </ns3:TimeRequiredToFull>
                <ns3:NotificationDateAndTime>2011-08-20T04:21:15.0</ns3:NotificationDateAndTime>
            </ns3:BatteryStatusRecords>
            <VehicleInfo>
                <Vin>**redacted**</Vin>
            </VehicleInfo>
            <lastBatteryStatusCheckExecutionTime>2011-08-20T04:20:59.000Z</lastBatteryStatusCheckExecutionTime>
        </SmartphoneBatteryStatusResponseType>
    </ns4:SmartphoneLatestBatteryStatusResponse>
    <ns4:SmartphoneLatestACStatusResponse>
        <SmartphoneACStatusResponseType>
            <ns3:RemoteACRecords>
                <ns3:OperationResult>FINISH</ns3:OperationResult>
                <ns3:OperationDateAndTime>2011-08-18T16:45:32.0</ns3:OperationDateAndTime>
                <ns3:RemoteACOperation>START</ns3:RemoteACOperation>
                <ns3:ACStartStopDateAndTime>2011-08-18T16:45:32.0</ns3:ACStartStopDateAndTime>
                <ns3:CruisingRangeAcOn>139608</ns3:CruisingRangeAcOn>
                <ns3:CruisingRangeAcOff>166200</ns3:CruisingRangeAcOff>
                <ns3:ACStartStopURL></ns3:ACStartStopURL>
                <ns3:PluginState>NOT_CONNECTED</ns3:PluginState>
                <ns3:ACDurationBatterySec>7200</ns3:ACDurationBatterySec>
                <ns3:ACDurationPluggedSec>900</ns3:ACDurationPluggedSec>
            </ns3:RemoteACRecords>
            <VehicleInfo>
                <Vin>**redacted**</Vin>
            </VehicleInfo>
        </SmartphoneACStatusResponseType>
    </ns4:SmartphoneLatestACStatusResponse>
    <ns2:SmartphoneGetPreferencesResponse>
        <NotificationPreferencesType>
            <vin>**redacted**</vin>
            <chargeStatusApple>false</chargeStatusApple>
            <chargeStatusEmail>false</chargeStatusEmail>
            <chargeStatusSms>false</chargeStatusSms>
            <plugInReminderApple>false</plugInReminderApple>
            <plugInReminderEmail>false</plugInReminderEmail>
            <plugInReminderSms>false</plugInReminderSms>
            <chargeCompleteApple>false</chargeCompleteApple>
            <chargeCompleteEmail>false</chargeCompleteEmail>
            <chargeCompleteSms>false</chargeCompleteSms>
            <hvacOnApple>false</hvacOnApple>
            <hvacOnEmail>false</hvacOnEmail>
            <hvacOnSms>false</hvacOnSms>
            <vehicleChargeApple>false</vehicleChargeApple>
            <vehicleChargeEmail>false</vehicleChargeEmail>
            <vehicleChargeSms>false</vehicleChargeSms>
        </NotificationPreferencesType>
    </ns2:SmartphoneGetPreferencesResponse>
    <ns6:SmartphoneRemoteGetScheduledACResponse>
        <SmartphoneRemoteGetScheduledACResponseType>
            <ns5:GetScheduledACRemoteResponse/>
            <VehicleInfo>
                <Vin>**redacted**</Vin>
            </VehicleInfo>
        </SmartphoneRemoteGetScheduledACResponseType>
    </ns6:SmartphoneRemoteGetScheduledACResponse>
</ns2:SmartphoneLoginWithAdditionalOperationResponse>

Note that you also get back a couple of cookies, which the client then passes back with each subsequent request.

If you request a charging update, the client then makes a call to https://nissan-na-smartphone-biz.viaaq.com/aqPortal/smartphoneProxy/vehicleService with the following payload:

Code:
<?xml version="1.0"?>
<ns4:SmartphoneRemoteBatteryStatusCheckRequest xmlns:ns4="urn:com:airbiquity:smartphone.vehicleservice:v1" xmlns:ns3="urn:com:hitachi:gdc:type:vehicle:v1" xmlns:ns2="urn:com:hitachi:gdc:type:portalcommon:v1">
  <ns3:BatteryStatusCheckRequest>
    <ns3:VehicleServiceRequestHeader>
      <ns2:VIN>**redacted**</ns2:VIN>
    </ns3:VehicleServiceRequestHeader>
  </ns3:BatteryStatusCheckRequest>
</ns4:SmartphoneRemoteBatteryStatusCheckRequest>

Which returns code 200 with no body. The client then calls https://nissan-na-smartphone-biz.viaaq.com/aqPortal/smartphoneProxy/userService which blocks. The request payload is:

Code:
<?xml version="1.0"?>
<ns2:SmartphoneGetVehicleInfoRequest xmlns:ns2="urn:com:airbiquity:smartphone.userservices:v1" xmlns:ns3="http://www.nissanusa.com/owners/schemas/api/0" xmlns:ns4="urn:com:hitachi:gdc:type:report:v1" xmlns:ns5="urn:com:airbiquity:smartphone.reportservice:v1" xmlns:ns6="urn:com:hitachi:gdc:type:vehicle:v1" xmlns:ns7="urn:com:airbiquity:smartphone.vehicleservice:v1">
  <VehicleInfo>
    <Vin>**redacted**</Vin>
  </VehicleInfo>
  <SmartphoneOperationType>SmartphoneGetPreferencesRequest</SmartphoneOperationType>
  <SmartphoneOperationType>SmartphoneLatestBatteryStatusRequest</SmartphoneOperationType>
  <SmartphoneOperationType>SmartphoneLatestACStatusRequest</SmartphoneOperationType>
  <SmartphoneOperationType>SmartphoneGetScheduledACRemoteRequest</SmartphoneOperationType>
  <changeVehicle>false</changeVehicle>
</ns2:SmartphoneGetVehicleInfoRequest>

After a few seconds, this call will return the following body:

Code:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ns2:SmartphoneGetVehicleInfoResponse xmlns:ns4="urn:com:airbiquity:smartphone.reportservice:v1" xmlns:ns7="urn:com:airbiquity:smartphone.common:v1" xmlns:ns3="urn:com:hitachi:gdc:type:report:v1" xmlns:ns5="urn:com:hitachi:gdc:type:vehicle:v1" xmlns:ns2="urn:com:airbiquity:smartphone.userservices:v1" xmlns:ns6="urn:com:airbiquity:smartphone.vehicleservice:v1">
    <ns4:SmartphoneLatestBatteryStatusResponse>
        <SmartphoneBatteryStatusResponseType>
            <ns3:BatteryStatusRecords>
                <ns3:OperationResult>START</ns3:OperationResult>
                <ns3:OperationDateAndTime>2011-08-20T06:08:35.0</ns3:OperationDateAndTime>
                <ns3:BatteryStatus>
                    <ns3:BatteryChargingStatus>NORMAL_CHARGING</ns3:BatteryChargingStatus>
                    <ns3:BatteryCapacity>12</ns3:BatteryCapacity>
                    <ns3:BatteryRemainingAmount>10</ns3:BatteryRemainingAmount>
                </ns3:BatteryStatus>
                <ns3:PluginState>CONNECTED</ns3:PluginState>
                <ns3:CruisingRangeAcOn>107616</ns3:CruisingRangeAcOn>
                <ns3:CruisingRangeAcOff>124032</ns3:CruisingRangeAcOff>
                <ns3:TimeRequiredToFull>
                    <ns3:HourRequiredToFull>3</ns3:HourRequiredToFull>
                    <ns3:MinutesRequiredToFull>30</ns3:MinutesRequiredToFull>
                </ns3:TimeRequiredToFull>
                <ns3:NotificationDateAndTime>2011-08-20T06:08:51.0</ns3:NotificationDateAndTime>
            </ns3:BatteryStatusRecords>
            <VehicleInfo>
                <Vin>**redacted**</Vin>
            </VehicleInfo>
            <lastBatteryStatusCheckExecutionTime>2011-08-20T06:08:35.000Z</lastBatteryStatusCheckExecutionTime>
        </SmartphoneBatteryStatusResponseType>
    </ns4:SmartphoneLatestBatteryStatusResponse>
    <ns4:SmartphoneLatestACStatusResponse>
        <SmartphoneACStatusResponseType>
            <ns3:RemoteACRecords>
                <ns3:OperationResult>FINISH</ns3:OperationResult>
                <ns3:OperationDateAndTime>2011-08-18T16:45:32.0</ns3:OperationDateAndTime>
                <ns3:RemoteACOperation>START</ns3:RemoteACOperation>
                <ns3:ACStartStopDateAndTime>2011-08-18T16:45:32.0</ns3:ACStartStopDateAndTime>
                <ns3:CruisingRangeAcOn>139608</ns3:CruisingRangeAcOn>
                <ns3:CruisingRangeAcOff>166200</ns3:CruisingRangeAcOff>
                <ns3:ACStartStopURL></ns3:ACStartStopURL>
                <ns3:PluginState>NOT_CONNECTED</ns3:PluginState>
                <ns3:ACDurationBatterySec>7200</ns3:ACDurationBatterySec>
                <ns3:ACDurationPluggedSec>900</ns3:ACDurationPluggedSec>
            </ns3:RemoteACRecords>
            <VehicleInfo>
                <Vin>**redacted**</Vin>
            </VehicleInfo>
        </SmartphoneACStatusResponseType>
    </ns4:SmartphoneLatestACStatusResponse>
    <ns2:SmartphoneGetPreferencesResponse>
        <NotificationPreferencesType>
            <vin>**redacted**</vin>
            <chargeStatusApple>false</chargeStatusApple>
            <chargeStatusEmail>false</chargeStatusEmail>
            <chargeStatusSms>false</chargeStatusSms>
            <plugInReminderApple>false</plugInReminderApple>
            <plugInReminderEmail>false</plugInReminderEmail>
            <plugInReminderSms>false</plugInReminderSms>
            <chargeCompleteApple>false</chargeCompleteApple>
            <chargeCompleteEmail>false</chargeCompleteEmail>
            <chargeCompleteSms>false</chargeCompleteSms>
            <hvacOnApple>false</hvacOnApple>
            <hvacOnEmail>false</hvacOnEmail>
            <hvacOnSms>false</hvacOnSms>
            <vehicleChargeApple>false</vehicleChargeApple>
            <vehicleChargeEmail>false</vehicleChargeEmail>
            <vehicleChargeSms>false</vehicleChargeSms>
        </NotificationPreferencesType>
    </ns2:SmartphoneGetPreferencesResponse>
    <ns6:SmartphoneRemoteGetScheduledACResponse>
        <SmartphoneRemoteGetScheduledACResponseType>
            <ns5:GetScheduledACRemoteResponse/>
            <VehicleInfo>
                <Vin>**redacted**</Vin>
            </VehicleInfo>
        </SmartphoneRemoteGetScheduledACResponseType>
    </ns6:SmartphoneRemoteGetScheduledACResponse>
</ns2:SmartphoneGetVehicleInfoResponse>

Obviously these responses are all for my car only, and for my specific settings, so your mileage may vary (hah!)

I'm hoping to use some of this stuff to build a web tool to let folks check charge state via SMS, or auto-post to twitter every so often etc. Anyone have any particular desires that I can aim for, in v1 of my tool? I intend to open-source everything I write.
 
I'm hoping to use some of this stuff to build a web tool to let folks check charge state via SMS, or auto-post to twitter every so often etc.

Hmm, like this?

http://www.mynissanleaf.com/viewtopic.php?f=34&t=3326&start=23
 
turbo2ltr said:
I'm hoping to use some of this stuff to build a web tool to let folks check charge state via SMS, or auto-post to twitter every so often etc.

Hmm, like this?

http://www.mynissanleaf.com/viewtopic.php?f=34&t=3326&start=23

That's definitely the inspiration. I'd like to do more with it, such as the SMS gateway etc.
 
Nice work on the RESTful analysis. I think this may be the basis of a Python app I could submit into the public domain because I think information should be free and wouldn't it be nice if you could do something like:

>>> import CARWINGS
>>> CARWINGS.get_SOC()
ValueError: Not logged in; please run the login() function
>>> CARWINGS.login(UID) # You can pass the password in the second parameter but it'd be plain text
Password: ******
>>> CARWINGS.get_SOC()
0.58
>>> CARWINGS.get_kWh()
13.92
>>> CARWINGS.get_est_charge_time() # This is in seconds
9450
>>> CARWINGS.get_est_charge_time(0.90) # To 90%
7200
>>> CARWINGS.get_est_trickle_time()
25200
>>> CARWINGS.start_climate()
>>> CARWINGS.is_climate_running()
True
>>> CARWINGS.start_charging()
>>> CARWINGS.is_charging()
True
>>> CARWINGS.stop_charging()
TypeError: Stupid CARWINGS API doesn't allow Charge Stop Messages. Phone Nissan and complain.

And finally with this I can program something like: If the get_est_charge_time < 14400, set local timer to send "start charging" even at 01:00; otherwise, set event for 0:00 - get_est_charge_time + 13000 (to finish charging by 5am). But evolve the program to take into account the true charge-time of the battery as observed since this changes with time. This would be much more accurate than the current charge timer which reads finish by 5am and typically finishes by 2:30. And I'm not going to explain why that's a major annoyance other than to say I have Time of Use metering.
 
Thanks again Ilya!

Now, having played a bit with pycarwings I think we may be able to safely say that yes, the car can only be directly measured by number of bars for the SOC. The Units are:

8%
17%
25%
33%
42%
50%
59% (was 58% but now seems to consistently report 59%)
67%
75%
83%
92%
100%

Not sure about the Low 1 and Low 2 and Turtle mode. This is disheartening but I think the web suffers the same limitation.

Interesting, with only 12 steps, there are more when computing the trickle charge time so it's more accurate to use in the 21 or maybe (though I don't recall seeing) 42 steps assuming time to charge is incorrectly calculated linearly rather than asymptotically since it will always slow as the battery reaches capacity.

So if we could use the trickle time for this purpose, we get units of:

5%, 10%, 14%, 19%, 24%, 29%, 33%, 38%, 43%, 48%, 52%, 57%, 62%, 67%, 71%, 76%, 81%, 86%, 90% and 100%

But here's the rub: my official numbers at the moment are 2 bars/17%/18 hours/5.5 hours. In the chart above, Trickle indicates 14% as opposed to 17% for bars and it must lie somewhere in there. If we assume 7 hours for the normal charging, we have at least 14 steps there and as such 21% represented by this measure.

So it's an interesting bag and a pity a better SOC isn't available.

And dang we still need a stop charge message!!

Edit: Well, it's not
Code:
SmartphoneRemoteBatteryStopRequest
...
 
I haven't played around enough with this yet, but if you're plugged into your L2 EVSE, I think it only reports the 240V charging time and not the 120V charging time.

Also the tapering doesn't appear to happen until very late in the charging cycle. My logs from my EVSE indicate very steady charging until the last 15 minutes or so (when going to 100% charge). Others have reported longer taper times, but even so even a 30-minute taper period is not going to throw the stats off by much.
 
And meanwhile,
Code:
SmartphoneRemoteBatteryChargeStopRequest
also doesn't work! I know, I know, it's probably not supported, there's probably no web interface to cease the charger but you never know, there could be a back door. But most likely, like I said before, we need to pester the hell out of Nissan to request this feature! :)

Oh, and yes, I verified senting two charge requests does not toggle the charger. The second one does nothing it just keeps charging. So much for that rumor now squashed.
 
Back
Top