Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for getting/setting charging schedule #227

Open
kalleguld opened this issue Sep 28, 2022 · 5 comments
Open

Support for getting/setting charging schedule #227

kalleguld opened this issue Sep 28, 2022 · 5 comments

Comments

@kalleguld
Copy link

Some EVs (eg. the Hyundai Ioniq 5) have the option of setting a charging schedule from the BlueLink App. Will it be possible to view and edit this schedule from BlueLinky?

Alternatively, if someone has an API description from Hyundai, I'd be happy to make a a pull request.

@Hacksore
Copy link
Owner

Possible but it would require someone to find the endpoints 😬.

@kalleguld
Copy link
Author

Do you have a good way of finding the endpoint? Decompilation? Wireshark?

@PierreLevres
Copy link
Contributor

Some python code I had working before I switched to Bluelinky and node-red completely

` def api_get_chargeschedule(self):
if not self.check_control_token(): return False
# location
url = BaseURL[self.userConfig.brand] + '/api/v2/spa/vehicles/' + self.vehicleConfig.id + '/reservation/charge'
headers = {
'Host': BaseHost[self.userConfig.brand], 'Accept': Accept,
'Authorization': self.controller.session.controlToken,
'ccsp-application-id': CcspApplicationId,
'Accept-Language': AcceptLanguage, 'Accept-Encoding': AcceptEncoding, 'offset': '2',
'stamp': self.controller.session.stamp,
'User-Agent': UserAgent, 'Connection': Connection, 'Content-Type': ContentJSON,
'ccsp-device-id': self.controller.session.deviceId
}
response = requests.get(url, headers=headers)
if response.status_code == 200:
try:
response = json.loads(response.text)
# TODO get schedule response
return response['resMsg']
except ValueError:
raise ApiError('NOK Parsing charge schedule: ' + response)
else:
raise ApiError('NOK requesting charge schedule. Error: ' + str(response.status_code) + response.text)

def api_set_chargeschedule(self, schedule1, schedule2, tempset, chargeschedule):
    # todo get input from formatted @dataclass
    '''
     Parameters Schedule1, Schedule2 = timeschedules for the temperature set
       first array [x,y,z, etc] with x,y,z, days that need to be set, where sunday = 0 and saturday = 6
       second the time and timesection in 12h notation, int or string, plus 0 or 1 (=AM or PM), int or string
       eg [[2,5,6],["1040","0"]] means 10:40 AM on Tuesday, Friday, Saturday

     Param Tempset
      first the temp to be set (in celcius), float or string
      second True or False for defrost on or off
      [23.0, True] means a temperature of 23 celsius and defrosting on

     ChargeSchedule
       first starttime = array time (int or string) and timesection 0 or 1 (AM or PM)
       then  endtime = array time (int or string) and timesection 0 or 1 (AM or PM)
       prio = 1 (only off-peak times) or 2 (prio to off-peak times)
     [["1100","1"],["0700","0"], 1 ] means off peak times are from 23:00 to 07:00 and car should only charge during these off peak times

     if any parameter = True or None, then ignore values. If parameter = False then disable the schedule, else set the values.
    '''
    if not self.check_control_token(): return False

    # first get the currens settings
    data = self.api_get_chargeschedule()
    olddata = data
    if not (not data):
        try:
            # now enter the new settings

            if not (schedule1 is None or schedule1 is True):  # ignore it of True or None
                if schedule1 is False:  # turn the schedule off
                    data['reservChargeInfo']['reservChargeInfoDetail']['reservChargeSet'] = False
                else:
                    data['reservChargeInfo']['reservChargeInfoDetail']['reservChargeSet'] = True
                    schedule = {"day": schedule1[0],
                                "time": {"time": str(schedule1[1][0]), "timeSection": int(schedule1[2][1])}}
                    data['reservChargeInfo']['reservChargeInfoDetail']['reservInfo'] = schedule
            if not (schedule2 is None or schedule2 is True):  # ignore it of True or None
                if schedule2 is False:  # turn the schedule off
                    data['reserveChargeInfo2']['reservChargeInfoDetail']['reservChargeSet'] = False
                else:
                    data['reserveChargeInfo2']['reservChargeInfoDetail']['reservChargeSet'] = True
                    schedule = {"day": schedule2[0],
                                "time": {"time": str(schedule2[1][0]), "timeSection": int(schedule2[2][1])}}
                    data['reserveChargeInfo2']['reservChargeInfoDetail']['reservInfo'] = schedule

            if not (tempset is None or tempset is True):  # ignore it of True or None
                if tempset is False:  # turn the schedule off
                    data['reservChargeInfo']['reservChargeInfoDetail']['reservFatcSet']['airCtrl'] = 0
                    data['reserveChargeInfo2']['reservChargeInfoDetail']['reservFatcSet']['airCtrl'] = 0
                else:
                    data['reservChargeInfo']['reservChargeInfoDetail']['reservFatcSet']['airCtrl'] = 1
                    data['reserveChargeInfo2']['reservChargeInfoDetail']['reservFatcSet']['airCtrl'] = 1
                    data['reservChargeInfo']['reservChargeInfoDetail']['reservFatcSet']['airTemp'][
                        'value'] = temp2hex(str(tempset[0]))
                    data['reserveChargeInfo2']['reservChargeInfoDetail']['reservFatcSet']['airTemp'][
                        'value'] = temp2hex(str(tempset[0]))
                    data['reservChargeInfo']['reservChargeInfoDetail']['reservFatcSet']['defrost'] = tempset[1]
                    data['reserveChargeInfo2']['reservChargeInfoDetail']['reservFatcSet']['defrost'] = tempset[1]

            if not (chargeschedule is None or chargeschedule is True):  # ignore it of True or None
                if chargeschedule is False:  # turn the schedule off
                    data['reservFlag'] = 0
                else:
                    data['reservFlag'] = 1
                    data['offPeakPowerInfo']['offPeakPowerTime1'] = {
                        "starttime": {"time": str(chargeschedule[0][1]), "timeSection": int(chargeschedule[0][1])},
                        "endtime": {"time": str(chargeschedule[1][1]), "timeSection": int(chargeschedule[1][1])}}
                    data['offPeakPowerInfo']['offPeakPowerFlag'] = int(chargeschedule[2])
            if data == olddata: return True  # nothing changed

            url = BaseURL[
                      self.userConfig.brand] + '/api/v2/spa/vehicles/' + self.vehicleConfig.id + '/reservation/charge'
            headers = {
                'Host': BaseHost[self.userConfig.brand], 'Accept': Accept,
                'Authorization': self.controller.session.controlToken,
                'ccsp-application-id': CcspApplicationId,
                'Accept-Language': AcceptLanguage, 'Accept-Encoding': AcceptEncoding, 'offset': '2',
                'User-Agent': UserAgent, 'Connection': Connection, 'Content-Type': ContentJSON,
                'stamp': self.controller.session.stamp,
                'ccsp-device-id': self.controller.session.deviceId
            }
            data['self.controller.session.deviceId'] = self.controller.session.deviceId
            response = requests.post(url, json=data, headers=headers)
            if response.status_code == 200: return True
        except:
            raise ApiError('NOK setting charge schedule.')
    raise ApiError('NOK setting charge schedule.')

`

@Hacksore
Copy link
Owner

@kalleguld
Copy link
Author

kalleguld commented Oct 5, 2022

GETting the /reservation/charge endpoint as @PierreLevres suggested works fine. But POSTing to that endpoint results in a 503 Service Unavailable message. Anyone got a clue?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants