Charging Your Phone, Your Way: Automation in 20 Minutes

Charging Your Phone, Your Way: Automation in 20 Minutes

You have a phone that’s permanently at home for some reason – maybe it’s acting as a replacement home phone, or maybe it’s a cheap throwaway for Pokémon Sleep.

But you know that keeping a battery charged at higher levels (be it 100% or even 80%) and/or running it down flat significantly tanks its life in the long term, so you want to prolong it by ensuring it always runs between some percentage range of your choice.

Automation is typically viewed as a very power user, “hack”-y kind of thing. You’ll feel right at home if you have a bit of basic understanding of programming and web dev, but not to fret – I’ll follow these steps with an explanation such that anybody should be able to follow along.

You’ll need

  • Your phone in question – I’ll be using a Motorola Edge 30 Pro
  • An automation app installed – I’ll be using MacroDroid
  • A smart plug that you will plug your charger into instead – I’ll be using an old WeMo Switch (as it’s called, not to be confused with the flick kind of switch)
  • That charger to ideally not be ultra/fast charging (the slower the better)
  • To agree with using IFTTT to get the job done – this is a minimal gear, 20 minute guide after all. By extension, that also means your smart plug should have IFTTT support
As of mid-February 2024, the following solution is a Pro feature. Still follow the instructions listed here, but instead take note of the changes in the new update, which provides a cheaper solution (free for Android, and very affordable for iOS/iPadOS).

What to do: IFTTT

  1. Sign up for an IFTTT account. As of writing, you’ll need to use both two of your available applets in the Free tier. This potentially means signing up with another email account if you don’t have Pro.
  2. If applicable, and you haven’t signed up for an account with your plug yet, do so now, as you’ll eventually need to integrate it with IFTTT.
  3. Create an applet in IFTTT [Pic 1].
    • If: Search for the Webhooks service, select it, then pick Receive a web request [Pic 2]. Name your event (say, smart_plug_on).
    • Then: Search for your plug’s service (e.g. WeMo) and select the plug, if appropriate (e.g. there’s also bulbs, toasters, etc) [Pic 3]. Then, select the on or off Action [Pic 4]. In my case, the Action settings will ask to link my account so that it can enumerate the plugs linked with it. From there, I can select the plug in question [Pic 5].
    • Connect the applet. That’s the giant slider.
  4. Create another applet using the above steps for the opposite on/off.
  5. Get your IFTTT API key.
    • Go to Explore in the header bar → Services → Search Webhooks → Webhooks. Here’s a link to Webhooks for your convenience:
    • Click on the second button labelled Documentation [Pic 6]. You will be taken to a page that contains your API key and instructions on how to use it.
    • (If you only see a Connect button, that means you’re not logged in.)
  6. Test your endpoint.
    • Connect a light or something to the plug to make it easy to tell that it’s working as expected.
    • Your URL should look something like https:// maker [dot] ifttt [dot] com/trigger/{eventName}/with/key/{key}. Access the appropriate on or off applet by going to it in your browser.

What to do: MacroDroid

  1. At the Home tab, go to Variables [Pic 1] to create a global variable ifttt_key (name is up to you) of type string, and set this to your API key.
  2. Switch to the Macros tab – let’s create our upper threshold macro first [Pic 2].
    • At the bottom of the screen is the Local Variables button. Tap this to create new local variables ifttt_command as string, set to the event name that you specified in IFTTT that will turn off your plug, and http_status as integer. You can name those variables whatever you like.
    • Trigger: Battery level increases to 70%.
    • Actions: Create then reorder them so they match the following.
      • Repeat actions → Do once and repeat → Add both these conditions, afterwards changing the condition from AND to OR. You can check the “don’t log condition failure” option to lessen the clutter of the logs.
        • MacroDroid Variable: http_status != 200
        • Power Connected: Any. Select all options, wired and wireless. I’m assuming you’re using a cable, but by all means if you wanna use a wireless charger, be my guest.
      • HTTP Request: GET request to the IFTTT URL, adding the local ifttt_command and global ifttt_key variables as appropriate by using the ... button to help you insert them. Check Block next actions until complete and Save HTTP return code in integer variable, selecting the http_status variable that we declared earlier [Pic 3].
      • Wait before next action: Define value, set an appropriate amount of time to wait for the smart plug to receive an instruction over the internet. 30 seconds should be generously patient enough.
      • If clause: Power Connected, all options. Don’t log condition failure unless you want it to show up in the system log.
      • [Optional] Log event: Write a message for the user log to explain that the power was still on when it shouldn’t have.
      • Display Notification: Send a notification so you know something’s failed. Customise to your liking; you probably also want to enable overwrite existing notification, which will replace an existing notification rather than add a new one on.
      • End if (automatically inserted).
      • End loop (automatically inserted).
      • [Optional] Log event: Write a message for the user log that this macro succeeded.
    • Constraints: None
  3. Clone the macro and change whatever needs flipping to match the lower threshold logic. This would be the trigger (battery level to ≤ 30%), power connected condition (to disconnected), local variable ifttt_command, and log messages.
    • For the lower threshold case, I had to additionally add a Screen On action as the first thing in the do/while loop. I give an explanation later.
  4. Clone the upper threshold macro again (the one created in step 2) to address the edge case where the phone above 70% is plugged into a plug that is on. Make the following modifications:
    • Trigger: Delete current trigger and replace with Power Connected, any kind.
    • Constraints: Battery level > 70%.

You should end up with something like [Pic 4].

The reason for the do/while loop is so that we keep retrying the URL request until it succeeds. If for some reason the phone didn’t have internet connection at the time of the request, the plug would entirely miss the call to turn off or on. Without the loop, the phone only contacts IFTTT once.

This happened during my test run when the phone was discharging: I got a host not found error, I didn’t have anything to handle this, and as a result the plug never switched back on, leaving the phone to run out of battery.

You should now have a setup where your smart plug will turn on and off in reaction to your phone’s battery level, allowing you to keep the USB cable plugged in to the charging adaptor. Hopefully, the phone should cycle between 70% and 30% (in this example), in a loop.

You might now wonder, but why go through all that trouble for this? Glad you asked, very good question, and don’t worry – I got you covered. Read on!

Context & Use Case

Imagine being on the NBN

Where I live, mobile plans with data end up being more affordable than the NBN equivalent, by a long shot. The idea of infinite data being the only option of plans these days across the board for a price hike of $20 sounded absurd to me, even if I was a data hoarder. Plus, 4G+ was just as fast as NBN25 under subpar conditions[1] – and yet a telco expects me to pay more for NBN12 speeds...

Then again, an average person these days would consider me data starved.[2] My monthly internet usage sums up to about 30ish gigabytes, a vast majority of which is involuntary (software updates of different flavours and devices, GIFs and videos that manage to thwart ad filters, etc). Hell, two gigabytes when I’m out and about is far too much for me to use in a whole year, solely because I’m never more than an hour’s away from a WiFi internet source.[3]

I can’t go with a mobile broadband only plan because I need to have the capability to make phone calls. A while ago, I bought a Huawei 5G modem with a phone port advertised as functional, but even with due diligence researching compatible bands and all that, my unused DECT phone stayed silent, and uh... unused. This venture ended up with me losing ~$170 post-refund due to postage, exchange rates, etc.

Such is the risk that’s not covered by Australian consumer law when you buy stuff from overseas...

The old “home” mobile

In the end, I stuck with my existing solution of using a perpetually at-home, hand-me-down mobile phone (Samsung Galaxy S6, to be exact). It was always plugged into the power point, so it never ran out of battery. This, as you’ll know, is terrible for its life. The S6 was built in a time when it wasn’t quite in vogue to halt charging earlier than the “100%” prescribed by the manufacturer.[4]

However, if you’ve used your phone to hotspot before, you’ll know that it burns a lot of battery power. Enough that you can’t “set and forget” it; 80% to 0% in about three hours is typical.[5] So, what do? Do I keep it plugged in, or left to drain?

Mind you, there were issues with the USB port on this phone: flimsy, had no grip of the plug, and needed precise wiggling and placement to maintain a connection. If it did manage to connect, I’d rather have left it kept plugged in and dealt with it suffering at 100%. If the cable fell off, I wouldn’t have known, and the way I’d realise is when my online voice chat would suddenly cut off.

Also, support for 3G was phasing out by the end of this year, and OTA update servers here never released a patch to enable the VoLTE toggle, or VoWiFi (not that that’s viable given it’ll be in hotspot mode anyways).

In other words, a phone was destined to lose its capabilities... as a phone.[6] Crazy, huh?

It’s worth mentioning, like my previous smartphone (the S4, pictured first below), the S6’s battery was starting to bulge, threatening to separate the phone’s back cover off. The fact that the S4 was released in 2013 speaks for how long I keep my phones for. Save the planet; don’t unnecessarily swap phones!

At any rate, all of these together are signs telling me it’s probably about high time I got a new one.

planned obsolescence, wew!

The Ideal Charge

I went ahead and got a Motorola Edge 30 Pro on special, the most value-for-money 5G phone I could get at that time (and for a good while, apparently). This time though, I wanted to properly do this battery thing right.

Battery University states that you get the best performance out of a lithium battery by:

  • Keeping the battery level between 30 and 80% (or really as close to half as you can). We’re going to go with 30 to 70.
  • Charging in smaller ranges and slower speeds, i.e. that 35 W charger that came with the phone is staying in its box.
  • Keeping the temperature cool. Not much we can do about this, so long as we’re not charging the phone underneath a pillow. I keep it on the TV table, which is made out of wood.

Dare I say, this sounds very much like a stomach when it comes to eating healthy loads (Japanese; bring your translator with you).

“Smart” charging

It should be noted that on my actual mobile phone (i.e. the one I carry with me), there’s a few ‘smart’ battery features:

  • Smart charge: “learns from your charging routine and delays fully charging past 80% until you need to use it”
  • Smart battery capacity: “finish charging just short of its actual peak capacity”

Personally, of the times where I’ve forgotten to unplug the phone, I’ve never seen either of these features trigger at all – and as such, I’d only trust myself to ensure the charging is going exactly as I want it to.

Besides, the idea is to prevent the battery from ever going to 100%, so postponing a full charge still doesn’t quite address the issue. The Motorola does have a hard stop feature at 80% equivalent to “smart battery capacity”, but it clarifies that to make this trigger, the phone must’ve been continuously plugged in for three days, which won’t necessarily be the case for me.

As we’re deciding on using only 40% of our battery on the Motorola, that equates to 1920 mAh, or about four hours, if we assume a hotspot power-hungry burn rate of 500 mA. Obviously, I won’t be capable of unplugging and replugging the power in every four hours, 24/7.

...But there is a tool for that.

The Smart Plug: Logic

A friend donated me his WeMo Switch, made by Belkin. He didn’t have a use for it given that he doesn’t need more automation that a simple analog timer couldn’t handle. Besides, his attempts to make the plug work didn’t fare well for him.

Out of the box, you can install the WeMo app on your device that has a simple toggle for you to turn it on and off. There’s also the ability to hook it up with Amazon Alexa, Google Assistant/Home, and IFTTT.

The overarching idea is to connect the ‘dumb’ charger to the ‘smart’ switch, enabling us to attach our own additional logic to it:

  • It’ll turn on when the phone’s battery goes below a threshold (30%), thus starting the charging process, simulating a connection to the charger
  • It’ll turn off when the phone’s battery goes above a threshold (70%), simulating a disconnection from the charger, or a plug pull

This by itself should be self-sufficient – provided, of course, if we need to unplug the phone for whatever reason, we don’t forget to plug it back in when done. Other situations to consider:

  • What happens when the phone, above the threshold, is connected when the plug is on (perhaps because it was switched on through other means)? → If so, automate the plug to turn off to prevent overcharging
  • What if the smart plug isn’t on when it’s supposed to (due to unexpected circumstances like connection errors) and the battery level is below the threshold? → When we connect the phone, we’d know that it was off (because the phone didn’t react), so we’d manually switch it on

An important note to make with MacroDroid is that the battery level threshold will only trigger once. Whilst the condition may be described as, say, “≤ 30”, this condition will only trigger at 31 → 30, and not again at 30 → 29, 29 → 28, etc.

Automation: Phone Side

Android has automation apps like the aptly named Automate, MacroDroid, and Tasker. I went with MacroDroid given that you can customise routines a fair bit. Tasker is a premium (i.e. upfront) paid app.

iOS’s equivalent of this is Shortcuts. Not surprisingly, as typical of Android vs Apple, Shortcuts’ interface is easier to use and understand, but comes with less features.

Regardless of operating system, both have knowledge about the device’s battery level, so you can leverage that to script the above smart plug logic.

Automation: Plug Side

The next problem to consider is how to tell the smart plug programmatically to change its state. Of course, we can manually bring an assistant up to command it to do things, but attempting to tell the phone to simulate this is impractical.

What if the phone is locked? What if we’re currently using it? Or, more amusingly, are we going to play a recorded clip of us saying “Hey Google/Siri/Alexa/Bixby/etc, trigger smart plug on” at 3:30 in the morning, loud enough in the hopes the nearby smart speaker picks it up? We need something more reliable and independent.

The Android automation apps provide no way to send commands to Assistant in the background; neither do they seem to have any out of the box IFTTT integrations. (I don’t use Alexa, so not sure about that one.)

What we do notice, though, is that we can access a URL resource. Or, in other words, an API call to an website that allows us to do what we need to do. So I’d expect something along the lines of<id>/run?key=<apiKey>.

Google Assistant very likely doesn’t do this sort of thing – and some research into this seemed to prove that was the case. However, luckily, IFTTT can.

And with that, we have an end-to-end path to get the job done!

Explaining the automation process

Here’s a more thorough walkthrough of the automation procedure, to switch the plug off (i.e. when the battery reaches 70%).

  • Do while http_status != 200 or power is connected
    • We want to run our procedure at least once; a do-while loop (run first, then check) will do just that, in contrast with a regular while loop (check first, then run).
    • As previously mentioned, if our URL endpoint fails the first time, having this loop exist will help us repeat calling the endpoint until it succeeds.
    • http_status is a local variable whose values only survive within each run of the macro. So, every time the macro is triggered, it will always start with a value of 0 (i.e. not 200), and thus meet the condition to run this macro.
    • Also, if the smart plug is still on after it’s been called to switch off, that in itself is proof our macro didn’t work, and that we should keep trying.
    • The two conditions have OR logic, not AND. If the URL endpoint succeeded, yet the smart plug remained on, it hasn’t done its job!
    • (Actually, now that I think about it, simply having “power is connected” should suffice as a condition, given that implies failure of the URL access...)
  • HTTP request (GET)
    • We insert the value of our variables using the ... button. Using variables for the IFTTT command and API key acts as a template of sorts, making it incredibly easy to clone this macro – we only need to change the command name via the local variables area, without needing to dig into the HTTP request screen to modify the URL.
    • Depending on the situation, when an HTTP request is sent, it’s not absolutely necessary to wait for the request to be complete. However, in this case, it is (because we need to know whether this request was successful to determine what to do next), so it’s appropriate here to check the box.
    • We know whether the request was successful if the response from the server returned 200. To use this return value in the other steps of the macro, we need to store it in a variable. This is why we need to have declared it beforehand.
  • Wait 30 seconds
    • Sending a message to IFTTT, which then sends a message to WeMo’s service, which the plug then needs to receive, may take a while, so we need to give it time.
    • More importantly, a pause should be implemented because otherwise MacroDroid will fire messages as fast as it can... which I’ll just say is very fast. Practice good API etiquette to avoid the 429 of shame!
  • If the smart plug didn’t do anything by this stage, we want the phone to let us know.
    • Logging a message is good for troubleshooting purposes.
    • However, even better is sending a notification, which alerts us visually, i.e. screen turns on in the lock screen, and audibly, should you wish to do so. I hope you set that 30 second timer properly, else you might be in for a huge surprise...

Macro Testing & Improvements

After putting together the macros and tweaking them as I go, I came across these observations and improvements.

IFTTT’s “200” status

Very early on, I found in my logs that MacroDroid’s call to IFTTT was always successful (i.e. returned 200), yet occasionally the power adaptor didn’t seem to reflect that.

I troubleshoot by going to the IFTTT endpoint’s URL myself, instantly seeing a confirmation message that I’ve successfully triggered the event, and then... nothing.

Sure, IFTTT may have received the message loud and clear, but they still had to forward the request onto WeMo’s services. The key issue here is that whilst IFTTT played its part, it has no way of letting us know whether WeMo did too.

In other words, we can’t trust IFTTT’s 200 status to determine whether the smart plug did something or not. However, we can still use it as a way to determine whether we can reach IFTTT. If not, then perhaps we just don’t have internet connectivity in the first place (this is tested by pinging Google).

Charge confirmation with AccuBattery

Before this automation project, I use AccuBattery for its notification alerts to remind me to pull the plug when it reaches my desired threshold.

Failed tries count

As the macros currently stand, the phone will keep sending IFTTT requests forever until the plug toggles and IFTTT returns 200. It might be a very good idea to introduce a failed_tries variable that counts retries, sending a notification only once per a certain number of attempts, rather than every time.

I’ll leave that with you to figure out how to do this, otherwise this article would get too confusing, as much as it already is right now. For starters, you may wish to explore MacroDroid’s various list of actions. Though, if you insist, I’ve taken a screenshot in this footnote. 👉🏻[7]

Issues with low battery threshold

Over three or so months of letting it do its thing, I’ve noticed that the phone will often fail to switch the smart plug on (i.e. low battery trigger) because it couldn’t connect to the internet. Yet, switching it off (i.e. high battery trigger) was perfectly fine.

As I’m getting the notifications from the failed tries count strategy above, I tried to find out what was wrong – but inadvertently, simply looking at these notifications on the lock screen was enough to successfully trigger the adaptor to turn on... 🤔

I initially thought there was some sort of hidden battery saving policy happening in the background – but the toggle for it is off in the settings. I then realised as I was writing my updated article that it was due to another app, AccuBattery, that sent a notification when the battery reached the upper threshold. This caused the phone screen to turn on and possibly allow the adaptor to toggle.

That said, hypothetically, if I tell MacroDroid to turn the screen on before calling IFTTT, it should solve the problem.

Thankfully, (a) MacroDroid has a Screen On action, and (b) this seems to have worked nicely and immediately. Well, at the very least, I’m getting a lot less failures compared to before.

Now it’s your turn

Those were my only issues that I’ve come across on this specific phone. If you experience other odd behaviour, it’s up to you to continue building your macro on top of what you have at the moment to cover these unforeseen situations. Good luck!

[1] Using the Galaxy S6, 4G+ typically maxes out at around 3 MB/s (note: capital B). This is in contrast with the Edge 30 Pro and my actual mobile phone, which both can reach speeds of up to 10 MB/s on the same network. It should also be noted that I get meh reception where I live, usually -105 to -100 dBm.

[2] The consequence to this is that I’m an uncultured swine when it comes to film and TV. I already get enough face rubbing from half of the content in a TV game shows’ question bank. But honestly, I don’t have a genuine interest in them.

This may have been the case a decade ago, where I hung out with the anime fansubbing scene, but today I’d much prefer content that I can read, such as light or visual novels. Of course, they take up significantly less disk space, too.

[3] Next time you get a chance to go on public transport, take a look around; see for yourself how incredibly amusing it is to find out how many “neck benders” there are relative to those who aren’t staring at their phones. Try not to be one of them.

I admit sometimes I indulge myself in being a phone zombie, but I’m also aware that it’s healthy to take a break and touch grass look tree. Listening to music is fine if you must, though there’s just something nice about a digital detox, no matter how brief.

Here’s a clip from TV show Parental Guidance on how kids from different parenting styles face a 24-hour no screen challenge.

[4] It’s possible to overcharge a battery in an attempt to maximise capacity, but this makes it dangerous and shortens its life, so a line has be to drawn somewhere. Typically, this is determined when the battery reaches 4.20 V, which is what I mean by prescribed.

[5] On the S6, average discharge rates were anywhere from 350 to 500 mA. That phone’s been through several hundred full charge cycle equivalents by now, so the 1600 mAh or so left on it would equate to about four hours’ life at best.

[6] Phone calls occur on the GSM (2G) or UMTS (3G) network only. As a result, the S6, not having that VoLTE toggle available, switches from 4G to 3G when a phone call is initiated – and typically, data rates slow to a halt whilst a call is being made.

Sometimes, I’ve discovered that calls will actually drop if I happen to be using data, so I always switch mobile data off to make sure I don’t drop out of my precious spot in that 45 minute phone queue. (I’m speaking from experience on this matter.)

[7] I get situations where I suspect the phone is disconnecting from the internet when not in use as the HTTP request to IFTTT fails with an unknown host error, so I’ve included a sanity test to ping Google. Additionally, I reduce spamming the logs by having said failed_tries variable. Also, perhaps a coincidence for now, the failures only occur on the <30% trigger.

A screenshot of my macro for the on routine when the battery level drops below 30%