Skip to content

Commit

Permalink
update auth process; implemented scan interval config; usage of HA ti…
Browse files Browse the repository at this point in the history
…mezone in ns uploader (#68)
  • Loading branch information
sedy89 authored Feb 22, 2024
1 parent 5bad17e commit e37a546
Show file tree
Hide file tree
Showing 25 changed files with 691 additions and 500 deletions.
42 changes: 42 additions & 0 deletions .devcontainer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
{
"name": "ludeeus/integration_blueprint",
"image": "mcr.microsoft.com/devcontainers/python:3.11-bullseye",
"postCreateCommand": "sudo -E bash scripts/setup",
"forwardPorts": [
8123
],
"portsAttributes": {
"8123": {
"label": "Home Assistant",
"onAutoForward": "notify"
}
},
"customizations": {
"vscode": {
"extensions": [
"ms-python.python",
"github.vscode-pull-request-github",
"ryanluker.vscode-coverage-gutters",
"ms-python.vscode-pylance"
],
"settings": {
"files.eol": "\n",
"editor.tabSize": 4,
"python.pythonPath": "/usr/bin/python3",
"python.analysis.autoSearchPaths": false,
"python.linting.pylintEnabled": true,
"python.linting.enabled": true,
"python.formatting.provider": "black",
"python.formatting.blackPath": "/usr/local/py-utils/bin/black",
"editor.formatOnPaste": false,
"editor.formatOnSave": true,
"editor.formatOnType": true,
"files.trimTrailingWhitespace": true
}
}
},
"remoteUser": "vscode",
"features": {
"ghcr.io/devcontainers/features/rust:1": {}
}
}
43 changes: 0 additions & 43 deletions .devcontainer/README.md

This file was deleted.

11 changes: 0 additions & 11 deletions .devcontainer/configuration.yml

This file was deleted.

43 changes: 0 additions & 43 deletions .devcontainer/devcontainer.json

This file was deleted.

5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -152,4 +152,7 @@ cython_debug/
#.idea/

*.DS_Store
cookies.txt
config/**
!config/configuration.yaml
/custom_components/carelink/logindata.json
/utils/logindata.json
22 changes: 2 additions & 20 deletions .vscode/tasks.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,9 @@
"version": "2.0.0",
"tasks": [
{
"label": "Run Home Assistant on port 9123",
"label": "Run Home Assistant on port 8123",
"type": "shell",
"command": "container start",
"problemMatcher": []
},
{
"label": "Run Home Assistant configuration against /config",
"type": "shell",
"command": "container check",
"problemMatcher": []
},
{
"label": "Upgrade Home Assistant to latest dev",
"type": "shell",
"command": "container install",
"problemMatcher": []
},
{
"label": "Install a specific version of Home Assistant",
"type": "shell",
"command": "container set-version",
"command": "sudo bash scripts/develop",
"problemMatcher": []
}
]
Expand Down
41 changes: 36 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,43 @@ Copy the `custom_components/carelink` to your `custom_components` folder. Reboot

## Integration Setup

### Session Token
In order to authenticate to the Carelink server, the Carelink client needs a valid access token. This can be obtained by manually logging into a Carelink follower account via Carelink web page. After successful login, the access token (plus country code) can be shown and copied using the Cookie Quick Manager Firefox plugin as follows:
### Carelink Login Data
The needed information for the authentification process can either be provided as file (=logindata.json), or entered during the initial setup of the integration.
#### Get the data
The Home Assistant Carelink Integration needs the initial login data stored in the `logindata.json` file. This file can be created **by running the login script on a PC with a screen**.
The login script from [@ondrej1024](https://github.com/ondrej1024)'s Carelink Python API, written by @palmarci (Pal Marci), was slightly modified and can be found here ["carelink_carepartner_api_login.py"](https://github.com/sedy89/Home-Assistant-Carelink/blob/json_login/utils/carelink_carepartner_api_login.py).

- With the Carelink web page still active, open Cookie Quick Manger from the extensions menu
- Select option "Search Cookies: carelink.minimed.eu"
- Copy value of auth temp token and use it as Session token for initial setup of the Homeassistant Carelink integration
Simply run:
```
python carelink_carepartner_api_login.py
```

You might need to install the following Python packages to satisfy the script's dependencies:

```
- requests
- OpenSSL (pip install pyOpenSSL)
- seleniumwire (pip install selenium-wire)
```

The script opens a Firefox web browser with the Carelink login page. You have to provide your Carelink patients or follower credentials (recommended) and solve the reCapcha.
On successful completion of the login, the data file will be created with the following structure:

![grafik](https://github.com/sedy89/Home-Assistant-Carelink/assets/65983953/35a60542-03fc-4deb-a14c-c96b0155bdd4)

#### Provide the data
Either the content of the `logindata.json` file can be taken over into the setup of the HA Carelink integration, or the entire file can be uploaded into the custom_componend/carelink folder (recommended).

![grafik](https://github.com/sedy89/Home-Assistant-Carelink/assets/65983953/0a1d8773-7905-4fec-9bff-b3a0f01817b9)

All parameters during setup are optional and a provided file will have a higher priority and overwrite the manual configuration.
If the file was copied to `custom_components/carelink` before the integration setup was started in Home Assistant, all parameters during the setup can stay empty.
With those information, the Home Assistant Carelink Integration will be able to automatically refresh the login data when it expires.
It should be able to do so within one week of the last refresh.

### Scan Interval
The scan interval of the integration can be configured during the integration setup.
User can configure anything between 30 and 300 seconds. Default is 60 seconds.

### Nightscout
To use the Nightscout uploader, it is mandatory to provide the Nightscout URL and the Nightscout API secret.
Expand Down
9 changes: 9 additions & 0 deletions config/configuration.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@

# Load frontend themes from the themes folder
frontend:
themes: !include_dir_merge_named themes

logger:
default: info
logs:
custom_components.carelink: debug
27 changes: 13 additions & 14 deletions custom_components/carelink/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
CLIENT,
UPLOADER,
DOMAIN,
SCAN_INTERVAL,
COORDINATOR,
UNAVAILABLE,
DEVICE_PUMP_MODEL,
Expand Down Expand Up @@ -82,8 +83,6 @@

_LOGGER = logging.getLogger(__name__)

SCAN_INTERVAL = timedelta(seconds=60)


def convert_date_to_isodate(date):
date_iso = re.sub("\.\d{3}Z$", "+00:00", date)
Expand All @@ -97,27 +96,26 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
hass.data.setdefault(DOMAIN, {})

config = entry.data
patientId = None

if "patientId" in config:
patientId = config["patientId"]

carelink_client = CarelinkClient(
config["country"],
config["token"],
patientId
config["cl_token"],
config["cl_refresh_token"],
config["cl_client_id"],
config["cl_client_secret"],
config["cl_mag_identifier"],
config["patientId"]
)

hass.data.setdefault(DOMAIN, {})[entry.entry_id] = {CLIENT: carelink_client}

if "nightscout_url" in config and "nightscout_api" in config:
if config["nightscout_url"] and config["nightscout_api"]:
nightscout_uploader = NightscoutUploader(
config["nightscout_url"],
config["nightscout_api"]
)
hass.data.setdefault(DOMAIN, {})[entry.entry_id].update({UPLOADER: nightscout_uploader})

coordinator = CarelinkCoordinator(hass, entry, update_interval=SCAN_INTERVAL)
coordinator = CarelinkCoordinator(hass, entry, update_interval=timedelta(seconds=config[SCAN_INTERVAL]))

await coordinator.async_config_entry_first_refresh()

Expand Down Expand Up @@ -163,9 +161,6 @@ async def _async_update_data(self):
recent_data = await self.client.get_recent_data()
if recent_data is None:
recent_data = dict()
else:
if self.uploader:
await self.uploader.send_recent_data(recent_data)
try:
if recent_data is not None and "clientTimeZoneName" in recent_data:
client_timezone = recent_data["clientTimeZoneName"]
Expand All @@ -188,6 +183,10 @@ async def _async_update_data(self):

_LOGGER.debug("Using timezone %s", DEFAULT_TIME_ZONE)

# nightscout uploader
if self.uploader:
await self.uploader.send_recent_data(recent_data, timezone)

recent_data["sLastSensorTime"] = recent_data.setdefault("sLastSensorTime", "")
recent_data["activeInsulin"] = recent_data.setdefault("activeInsulin", {})
recent_data["basal"] = recent_data.setdefault("basal", {})
Expand Down
Loading

0 comments on commit e37a546

Please sign in to comment.