Improve auth-flow & check killswitch every 15min - #54

Open
jacobbaungard wants to merge 9 commits into
faanskit:masterfrom
jacobbaungard:check-jwt-expiry
Open

Improve auth-flow & check killswitch every 15min#54
jacobbaungard wants to merge 9 commits into
faanskit:masterfrom
jacobbaungard:check-jwt-expiry

Conversation

@jacobbaungard

Copy link
Copy Markdown

Auth flow
Instead of doing a full login flow at every update (i.e 1 min interval from HA), we re-use the JWT token if possible. If the JWT token is expired, we refresh the token if possible, instead of running the full login flow. This should be a much more efficient flow. When checking expire of the jwt/refresh token, we add a one minute margin, to ensure clients have time to complete their requests after the login flow.

Clients will need to pass in (by reference) a CheckwattStateInfo. This is meant to keep the state in memory between multiple CheckwattManagers (HA creates a new one every update, perhaps that can be changed in the future).

Kill switch
It turns out the checking of the killswitch is what causes the 429 seen in various installations. After agreement
with CW, with this PR we check it only every 15minute, which should lower the load on CWs server significantly.

On startup we check the killswitch immediately, and then generate a random time interval for the next check. This should ensure the load gets evenly spread out between installations.

Testing
I've tested this quite a bit over the last week or so, making adjusts as I go. Everything seems to work fine, although in my installation I still get 429s when checking the killswitch - likely we'd need many people to update before we see the effect of this change.

If someone wants to test this on an actual HA installation, this is how I've run my docker-based HA installation:

  • Create a new dockerfile for HA:
FROM homeassistant/home-assistant:2025.8.3
RUN git clone -b check-jwt-expiry https://github.com/jacobbaungard/pyCheckwatt.git /tmp/pyCheckwatt
RUN pip install -e /tmp/pyCheckwatt/

You may also want to increase the logging level to debug while testing:

logger:
logs:
custom_components.checkwatt: debug
pycheckwatt: debug

Signed-off-by: Jacob Baungard Hansen <me@jacobbaungard.com>
This commit ensures we can re-use JWT tokens, and refresh accordingly,
instead of relogging every time, which often causes 429/rate-limits from
checkwatt.
The client of the library should pass in an authinfo object (by
reference) when using the manager. The manager will update any info in
the authinfo object as needed.
Signed-off-by: Jacob Baungard Hansen <me@jacobbaungard.com>
The killswitch suffers often from 429/too many requests. After agreement
with CW, we check it only every 15minute.
On startup we check it immediately, and then generate a random time
interval for the next check. This should ensure the load gets evenly
spread out between installations.
Add a one minute margin to the JWT/refresh token expiry checks to ensure
the token doesn't expire shortly after the check.
So they work with the new stateinfo object.

@mattiasclaessonmattiasclaesson left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Think this is the correct way to go. I will take a look at the other suggestions from @jenshorn aswell.

Looks like we need a PR on the ha-checkwatt as well for the auth_info?

Could we rely on the checkwatt server to complain if the tokens are not valid? Instead of having the client check the token?

@jacobbaungard

jacobbaungard commented Jul 6, 2026

Copy link
Copy Markdown
Author

Looks like we need a PR on the ha-checkwatt as well for the auth_info?

Yes. If this get merges, that is needed. I have an implementation ready here https://github.com/jacobbaungard/ha-checkwatt/tree/reuse-cw-object

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@jacobbaungard@mattiasclaesson
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Improve auth-flow & check killswitch every 15min - #54

Open
jacobbaungard wants to merge 9 commits into
faanskit:masterfrom
jacobbaungard:check-jwt-expiry
Open

Improve auth-flow & check killswitch every 15min#54
jacobbaungard wants to merge 9 commits into
faanskit:masterfrom
jacobbaungard:check-jwt-expiry

Conversation

@jacobbaungard

Copy link
Copy Markdown

Auth flow
Instead of doing a full login flow at every update (i.e 1 min interval from HA), we re-use the JWT token if possible. If the JWT token is expired, we refresh the token if possible, instead of running the full login flow. This should be a much more efficient flow. When checking expire of the jwt/refresh token, we add a one minute margin, to ensure clients have time to complete their requests after the login flow.

Clients will need to pass in (by reference) a CheckwattStateInfo. This is meant to keep the state in memory between multiple CheckwattManagers (HA creates a new one every update, perhaps that can be changed in the future).

Kill switch
It turns out the checking of the killswitch is what causes the 429 seen in various installations. After agreement
with CW, with this PR we check it only every 15minute, which should lower the load on CWs server significantly.

On startup we check the killswitch immediately, and then generate a random time interval for the next check. This should ensure the load gets evenly spread out between installations.

Testing
I've tested this quite a bit over the last week or so, making adjusts as I go. Everything seems to work fine, although in my installation I still get 429s when checking the killswitch - likely we'd need many people to update before we see the effect of this change.

If someone wants to test this on an actual HA installation, this is how I've run my docker-based HA installation:

  • Create a new dockerfile for HA:
FROM homeassistant/home-assistant:2025.8.3
RUN git clone -b check-jwt-expiry https://github.com/jacobbaungard/pyCheckwatt.git /tmp/pyCheckwatt
RUN pip install -e /tmp/pyCheckwatt/

You may also want to increase the logging level to debug while testing:

logger:
logs:
custom_components.checkwatt: debug
pycheckwatt: debug

Signed-off-by: Jacob Baungard Hansen <me@jacobbaungard.com>
This commit ensures we can re-use JWT tokens, and refresh accordingly,
instead of relogging every time, which often causes 429/rate-limits from
checkwatt.
The client of the library should pass in an authinfo object (by
reference) when using the manager. The manager will update any info in
the authinfo object as needed.
Signed-off-by: Jacob Baungard Hansen <me@jacobbaungard.com>
The killswitch suffers often from 429/too many requests. After agreement
with CW, we check it only every 15minute.
On startup we check it immediately, and then generate a random time
interval for the next check. This should ensure the load gets evenly
spread out between installations.
Add a one minute margin to the JWT/refresh token expiry checks to ensure
the token doesn't expire shortly after the check.
So they work with the new stateinfo object.

@mattiasclaessonmattiasclaesson left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Think this is the correct way to go. I will take a look at the other suggestions from @jenshorn aswell.

Looks like we need a PR on the ha-checkwatt as well for the auth_info?

Could we rely on the checkwatt server to complain if the tokens are not valid? Instead of having the client check the token?

@jacobbaungard

jacobbaungard commented Jul 6, 2026

Copy link
Copy Markdown
Author

Looks like we need a PR on the ha-checkwatt as well for the auth_info?

Yes. If this get merges, that is needed. I have an implementation ready here https://github.com/jacobbaungard/ha-checkwatt/tree/reuse-cw-object

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@jacobbaungard@mattiasclaesson
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Improve auth-flow & check killswitch every 15min - #54

Open
jacobbaungard wants to merge 9 commits into
faanskit:masterfrom
jacobbaungard:check-jwt-expiry
Open

Improve auth-flow & check killswitch every 15min#54
jacobbaungard wants to merge 9 commits into
faanskit:masterfrom
jacobbaungard:check-jwt-expiry

Conversation

@jacobbaungard

Copy link
Copy Markdown

Auth flow
Instead of doing a full login flow at every update (i.e 1 min interval from HA), we re-use the JWT token if possible. If the JWT token is expired, we refresh the token if possible, instead of running the full login flow. This should be a much more efficient flow. When checking expire of the jwt/refresh token, we add a one minute margin, to ensure clients have time to complete their requests after the login flow.

Clients will need to pass in (by reference) a CheckwattStateInfo. This is meant to keep the state in memory between multiple CheckwattManagers (HA creates a new one every update, perhaps that can be changed in the future).

Kill switch
It turns out the checking of the killswitch is what causes the 429 seen in various installations. After agreement
with CW, with this PR we check it only every 15minute, which should lower the load on CWs server significantly.

On startup we check the killswitch immediately, and then generate a random time interval for the next check. This should ensure the load gets evenly spread out between installations.

Testing
I've tested this quite a bit over the last week or so, making adjusts as I go. Everything seems to work fine, although in my installation I still get 429s when checking the killswitch - likely we'd need many people to update before we see the effect of this change.

If someone wants to test this on an actual HA installation, this is how I've run my docker-based HA installation:

  • Create a new dockerfile for HA:
FROM homeassistant/home-assistant:2025.8.3
RUN git clone -b check-jwt-expiry https://github.com/jacobbaungard/pyCheckwatt.git /tmp/pyCheckwatt
RUN pip install -e /tmp/pyCheckwatt/

You may also want to increase the logging level to debug while testing:

logger:
logs:
custom_components.checkwatt: debug
pycheckwatt: debug

Signed-off-by: Jacob Baungard Hansen <me@jacobbaungard.com>
This commit ensures we can re-use JWT tokens, and refresh accordingly,
instead of relogging every time, which often causes 429/rate-limits from
checkwatt.
The client of the library should pass in an authinfo object (by
reference) when using the manager. The manager will update any info in
the authinfo object as needed.
Signed-off-by: Jacob Baungard Hansen <me@jacobbaungard.com>
The killswitch suffers often from 429/too many requests. After agreement
with CW, we check it only every 15minute.
On startup we check it immediately, and then generate a random time
interval for the next check. This should ensure the load gets evenly
spread out between installations.
Add a one minute margin to the JWT/refresh token expiry checks to ensure
the token doesn't expire shortly after the check.
So they work with the new stateinfo object.

@mattiasclaessonmattiasclaesson left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Think this is the correct way to go. I will take a look at the other suggestions from @jenshorn aswell.

Looks like we need a PR on the ha-checkwatt as well for the auth_info?

Could we rely on the checkwatt server to complain if the tokens are not valid? Instead of having the client check the token?

@jacobbaungard

jacobbaungard commented Jul 6, 2026

Copy link
Copy Markdown
Author

Looks like we need a PR on the ha-checkwatt as well for the auth_info?

Yes. If this get merges, that is needed. I have an implementation ready here https://github.com/jacobbaungard/ha-checkwatt/tree/reuse-cw-object

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@jacobbaungard@mattiasclaesson
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Improve auth-flow & check killswitch every 15min - #54

Open
jacobbaungard wants to merge 9 commits into
faanskit:masterfrom
jacobbaungard:check-jwt-expiry
Open

Improve auth-flow & check killswitch every 15min#54
jacobbaungard wants to merge 9 commits into
faanskit:masterfrom
jacobbaungard:check-jwt-expiry

Conversation

@jacobbaungard

Copy link
Copy Markdown

Auth flow
Instead of doing a full login flow at every update (i.e 1 min interval from HA), we re-use the JWT token if possible. If the JWT token is expired, we refresh the token if possible, instead of running the full login flow. This should be a much more efficient flow. When checking expire of the jwt/refresh token, we add a one minute margin, to ensure clients have time to complete their requests after the login flow.

Clients will need to pass in (by reference) a CheckwattStateInfo. This is meant to keep the state in memory between multiple CheckwattManagers (HA creates a new one every update, perhaps that can be changed in the future).

Kill switch
It turns out the checking of the killswitch is what causes the 429 seen in various installations. After agreement
with CW, with this PR we check it only every 15minute, which should lower the load on CWs server significantly.

On startup we check the killswitch immediately, and then generate a random time interval for the next check. This should ensure the load gets evenly spread out between installations.

Testing
I've tested this quite a bit over the last week or so, making adjusts as I go. Everything seems to work fine, although in my installation I still get 429s when checking the killswitch - likely we'd need many people to update before we see the effect of this change.

If someone wants to test this on an actual HA installation, this is how I've run my docker-based HA installation:

  • Create a new dockerfile for HA:
FROM homeassistant/home-assistant:2025.8.3
RUN git clone -b check-jwt-expiry https://github.com/jacobbaungard/pyCheckwatt.git /tmp/pyCheckwatt
RUN pip install -e /tmp/pyCheckwatt/

You may also want to increase the logging level to debug while testing:

logger:
logs:
custom_components.checkwatt: debug
pycheckwatt: debug

Signed-off-by: Jacob Baungard Hansen <me@jacobbaungard.com>
This commit ensures we can re-use JWT tokens, and refresh accordingly,
instead of relogging every time, which often causes 429/rate-limits from
checkwatt.
The client of the library should pass in an authinfo object (by
reference) when using the manager. The manager will update any info in
the authinfo object as needed.
Signed-off-by: Jacob Baungard Hansen <me@jacobbaungard.com>
The killswitch suffers often from 429/too many requests. After agreement
with CW, we check it only every 15minute.
On startup we check it immediately, and then generate a random time
interval for the next check. This should ensure the load gets evenly
spread out between installations.
Add a one minute margin to the JWT/refresh token expiry checks to ensure
the token doesn't expire shortly after the check.
So they work with the new stateinfo object.

@mattiasclaessonmattiasclaesson left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Think this is the correct way to go. I will take a look at the other suggestions from @jenshorn aswell.

Looks like we need a PR on the ha-checkwatt as well for the auth_info?

Could we rely on the checkwatt server to complain if the tokens are not valid? Instead of having the client check the token?

@jacobbaungard

jacobbaungard commented Jul 6, 2026

Copy link
Copy Markdown
Author

Looks like we need a PR on the ha-checkwatt as well for the auth_info?

Yes. If this get merges, that is needed. I have an implementation ready here https://github.com/jacobbaungard/ha-checkwatt/tree/reuse-cw-object

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@jacobbaungard@mattiasclaesson
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Improve auth-flow & check killswitch every 15min - #54

Open
jacobbaungard wants to merge 9 commits into
faanskit:masterfrom
jacobbaungard:check-jwt-expiry
Open

Improve auth-flow & check killswitch every 15min#54
jacobbaungard wants to merge 9 commits into
faanskit:masterfrom
jacobbaungard:check-jwt-expiry

Conversation

@jacobbaungard

Copy link
Copy Markdown

Auth flow
Instead of doing a full login flow at every update (i.e 1 min interval from HA), we re-use the JWT token if possible. If the JWT token is expired, we refresh the token if possible, instead of running the full login flow. This should be a much more efficient flow. When checking expire of the jwt/refresh token, we add a one minute margin, to ensure clients have time to complete their requests after the login flow.

Clients will need to pass in (by reference) a CheckwattStateInfo. This is meant to keep the state in memory between multiple CheckwattManagers (HA creates a new one every update, perhaps that can be changed in the future).

Kill switch
It turns out the checking of the killswitch is what causes the 429 seen in various installations. After agreement
with CW, with this PR we check it only every 15minute, which should lower the load on CWs server significantly.

On startup we check the killswitch immediately, and then generate a random time interval for the next check. This should ensure the load gets evenly spread out between installations.

Testing
I've tested this quite a bit over the last week or so, making adjusts as I go. Everything seems to work fine, although in my installation I still get 429s when checking the killswitch - likely we'd need many people to update before we see the effect of this change.

If someone wants to test this on an actual HA installation, this is how I've run my docker-based HA installation:

  • Create a new dockerfile for HA:
FROM homeassistant/home-assistant:2025.8.3
RUN git clone -b check-jwt-expiry https://github.com/jacobbaungard/pyCheckwatt.git /tmp/pyCheckwatt
RUN pip install -e /tmp/pyCheckwatt/

You may also want to increase the logging level to debug while testing:

logger:
logs:
custom_components.checkwatt: debug
pycheckwatt: debug

Signed-off-by: Jacob Baungard Hansen <me@jacobbaungard.com>
This commit ensures we can re-use JWT tokens, and refresh accordingly,
instead of relogging every time, which often causes 429/rate-limits from
checkwatt.
The client of the library should pass in an authinfo object (by
reference) when using the manager. The manager will update any info in
the authinfo object as needed.
Signed-off-by: Jacob Baungard Hansen <me@jacobbaungard.com>
The killswitch suffers often from 429/too many requests. After agreement
with CW, we check it only every 15minute.
On startup we check it immediately, and then generate a random time
interval for the next check. This should ensure the load gets evenly
spread out between installations.
Add a one minute margin to the JWT/refresh token expiry checks to ensure
the token doesn't expire shortly after the check.
So they work with the new stateinfo object.

@mattiasclaessonmattiasclaesson left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Think this is the correct way to go. I will take a look at the other suggestions from @jenshorn aswell.

Looks like we need a PR on the ha-checkwatt as well for the auth_info?

Could we rely on the checkwatt server to complain if the tokens are not valid? Instead of having the client check the token?

@jacobbaungard

jacobbaungard commented Jul 6, 2026

Copy link
Copy Markdown
Author

Looks like we need a PR on the ha-checkwatt as well for the auth_info?

Yes. If this get merges, that is needed. I have an implementation ready here https://github.com/jacobbaungard/ha-checkwatt/tree/reuse-cw-object

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@jacobbaungard@mattiasclaesson
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Improve auth-flow & check killswitch every 15min - #54

Open
jacobbaungard wants to merge 9 commits into
faanskit:masterfrom
jacobbaungard:check-jwt-expiry
Open

Improve auth-flow & check killswitch every 15min#54
jacobbaungard wants to merge 9 commits into
faanskit:masterfrom
jacobbaungard:check-jwt-expiry

Conversation

@jacobbaungard

Copy link
Copy Markdown

Auth flow
Instead of doing a full login flow at every update (i.e 1 min interval from HA), we re-use the JWT token if possible. If the JWT token is expired, we refresh the token if possible, instead of running the full login flow. This should be a much more efficient flow. When checking expire of the jwt/refresh token, we add a one minute margin, to ensure clients have time to complete their requests after the login flow.

Clients will need to pass in (by reference) a CheckwattStateInfo. This is meant to keep the state in memory between multiple CheckwattManagers (HA creates a new one every update, perhaps that can be changed in the future).

Kill switch
It turns out the checking of the killswitch is what causes the 429 seen in various installations. After agreement
with CW, with this PR we check it only every 15minute, which should lower the load on CWs server significantly.

On startup we check the killswitch immediately, and then generate a random time interval for the next check. This should ensure the load gets evenly spread out between installations.

Testing
I've tested this quite a bit over the last week or so, making adjusts as I go. Everything seems to work fine, although in my installation I still get 429s when checking the killswitch - likely we'd need many people to update before we see the effect of this change.

If someone wants to test this on an actual HA installation, this is how I've run my docker-based HA installation:

  • Create a new dockerfile for HA:
FROM homeassistant/home-assistant:2025.8.3
RUN git clone -b check-jwt-expiry https://github.com/jacobbaungard/pyCheckwatt.git /tmp/pyCheckwatt
RUN pip install -e /tmp/pyCheckwatt/

You may also want to increase the logging level to debug while testing:

logger:
logs:
custom_components.checkwatt: debug
pycheckwatt: debug

Signed-off-by: Jacob Baungard Hansen <me@jacobbaungard.com>
This commit ensures we can re-use JWT tokens, and refresh accordingly,
instead of relogging every time, which often causes 429/rate-limits from
checkwatt.
The client of the library should pass in an authinfo object (by
reference) when using the manager. The manager will update any info in
the authinfo object as needed.
Signed-off-by: Jacob Baungard Hansen <me@jacobbaungard.com>
The killswitch suffers often from 429/too many requests. After agreement
with CW, we check it only every 15minute.
On startup we check it immediately, and then generate a random time
interval for the next check. This should ensure the load gets evenly
spread out between installations.
Add a one minute margin to the JWT/refresh token expiry checks to ensure
the token doesn't expire shortly after the check.
So they work with the new stateinfo object.

@mattiasclaessonmattiasclaesson left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Think this is the correct way to go. I will take a look at the other suggestions from @jenshorn aswell.

Looks like we need a PR on the ha-checkwatt as well for the auth_info?

Could we rely on the checkwatt server to complain if the tokens are not valid? Instead of having the client check the token?

@jacobbaungard

jacobbaungard commented Jul 6, 2026

Copy link
Copy Markdown
Author

Looks like we need a PR on the ha-checkwatt as well for the auth_info?

Yes. If this get merges, that is needed. I have an implementation ready here https://github.com/jacobbaungard/ha-checkwatt/tree/reuse-cw-object

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@jacobbaungard@mattiasclaesson
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Improve auth-flow & check killswitch every 15min - #54

Open
jacobbaungard wants to merge 9 commits into
faanskit:masterfrom
jacobbaungard:check-jwt-expiry
Open

Improve auth-flow & check killswitch every 15min#54
jacobbaungard wants to merge 9 commits into
faanskit:masterfrom
jacobbaungard:check-jwt-expiry

Conversation

@jacobbaungard

Copy link
Copy Markdown

Auth flow
Instead of doing a full login flow at every update (i.e 1 min interval from HA), we re-use the JWT token if possible. If the JWT token is expired, we refresh the token if possible, instead of running the full login flow. This should be a much more efficient flow. When checking expire of the jwt/refresh token, we add a one minute margin, to ensure clients have time to complete their requests after the login flow.

Clients will need to pass in (by reference) a CheckwattStateInfo. This is meant to keep the state in memory between multiple CheckwattManagers (HA creates a new one every update, perhaps that can be changed in the future).

Kill switch
It turns out the checking of the killswitch is what causes the 429 seen in various installations. After agreement
with CW, with this PR we check it only every 15minute, which should lower the load on CWs server significantly.

On startup we check the killswitch immediately, and then generate a random time interval for the next check. This should ensure the load gets evenly spread out between installations.

Testing
I've tested this quite a bit over the last week or so, making adjusts as I go. Everything seems to work fine, although in my installation I still get 429s when checking the killswitch - likely we'd need many people to update before we see the effect of this change.

If someone wants to test this on an actual HA installation, this is how I've run my docker-based HA installation:

  • Create a new dockerfile for HA:
FROM homeassistant/home-assistant:2025.8.3
RUN git clone -b check-jwt-expiry https://github.com/jacobbaungard/pyCheckwatt.git /tmp/pyCheckwatt
RUN pip install -e /tmp/pyCheckwatt/

You may also want to increase the logging level to debug while testing:

logger:
logs:
custom_components.checkwatt: debug
pycheckwatt: debug

Signed-off-by: Jacob Baungard Hansen <me@jacobbaungard.com>
This commit ensures we can re-use JWT tokens, and refresh accordingly,
instead of relogging every time, which often causes 429/rate-limits from
checkwatt.
The client of the library should pass in an authinfo object (by
reference) when using the manager. The manager will update any info in
the authinfo object as needed.
Signed-off-by: Jacob Baungard Hansen <me@jacobbaungard.com>
The killswitch suffers often from 429/too many requests. After agreement
with CW, we check it only every 15minute.
On startup we check it immediately, and then generate a random time
interval for the next check. This should ensure the load gets evenly
spread out between installations.
Add a one minute margin to the JWT/refresh token expiry checks to ensure
the token doesn't expire shortly after the check.
So they work with the new stateinfo object.

@mattiasclaessonmattiasclaesson left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Think this is the correct way to go. I will take a look at the other suggestions from @jenshorn aswell.

Looks like we need a PR on the ha-checkwatt as well for the auth_info?

Could we rely on the checkwatt server to complain if the tokens are not valid? Instead of having the client check the token?

@jacobbaungard

jacobbaungard commented Jul 6, 2026

Copy link
Copy Markdown
Author

Looks like we need a PR on the ha-checkwatt as well for the auth_info?

Yes. If this get merges, that is needed. I have an implementation ready here https://github.com/jacobbaungard/ha-checkwatt/tree/reuse-cw-object

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@jacobbaungard@mattiasclaesson
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Improve auth-flow & check killswitch every 15min - #54

Open
jacobbaungard wants to merge 9 commits into
faanskit:masterfrom
jacobbaungard:check-jwt-expiry
Open

Improve auth-flow & check killswitch every 15min#54
jacobbaungard wants to merge 9 commits into
faanskit:masterfrom
jacobbaungard:check-jwt-expiry

Conversation

@jacobbaungard

Copy link
Copy Markdown

Auth flow
Instead of doing a full login flow at every update (i.e 1 min interval from HA), we re-use the JWT token if possible. If the JWT token is expired, we refresh the token if possible, instead of running the full login flow. This should be a much more efficient flow. When checking expire of the jwt/refresh token, we add a one minute margin, to ensure clients have time to complete their requests after the login flow.

Clients will need to pass in (by reference) a CheckwattStateInfo. This is meant to keep the state in memory between multiple CheckwattManagers (HA creates a new one every update, perhaps that can be changed in the future).

Kill switch
It turns out the checking of the killswitch is what causes the 429 seen in various installations. After agreement
with CW, with this PR we check it only every 15minute, which should lower the load on CWs server significantly.

On startup we check the killswitch immediately, and then generate a random time interval for the next check. This should ensure the load gets evenly spread out between installations.

Testing
I've tested this quite a bit over the last week or so, making adjusts as I go. Everything seems to work fine, although in my installation I still get 429s when checking the killswitch - likely we'd need many people to update before we see the effect of this change.

If someone wants to test this on an actual HA installation, this is how I've run my docker-based HA installation:

  • Create a new dockerfile for HA:
FROM homeassistant/home-assistant:2025.8.3
RUN git clone -b check-jwt-expiry https://github.com/jacobbaungard/pyCheckwatt.git /tmp/pyCheckwatt
RUN pip install -e /tmp/pyCheckwatt/

You may also want to increase the logging level to debug while testing:

logger:
logs:
custom_components.checkwatt: debug
pycheckwatt: debug

Signed-off-by: Jacob Baungard Hansen <me@jacobbaungard.com>
This commit ensures we can re-use JWT tokens, and refresh accordingly,
instead of relogging every time, which often causes 429/rate-limits from
checkwatt.
The client of the library should pass in an authinfo object (by
reference) when using the manager. The manager will update any info in
the authinfo object as needed.
Signed-off-by: Jacob Baungard Hansen <me@jacobbaungard.com>
The killswitch suffers often from 429/too many requests. After agreement
with CW, we check it only every 15minute.
On startup we check it immediately, and then generate a random time
interval for the next check. This should ensure the load gets evenly
spread out between installations.
Add a one minute margin to the JWT/refresh token expiry checks to ensure
the token doesn't expire shortly after the check.
So they work with the new stateinfo object.

@mattiasclaessonmattiasclaesson left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Think this is the correct way to go. I will take a look at the other suggestions from @jenshorn aswell.

Looks like we need a PR on the ha-checkwatt as well for the auth_info?

Could we rely on the checkwatt server to complain if the tokens are not valid? Instead of having the client check the token?

@jacobbaungard

jacobbaungard commented Jul 6, 2026

Copy link
Copy Markdown
Author

Looks like we need a PR on the ha-checkwatt as well for the auth_info?

Yes. If this get merges, that is needed. I have an implementation ready here https://github.com/jacobbaungard/ha-checkwatt/tree/reuse-cw-object

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@jacobbaungard@mattiasclaesson