HackGPT - Creating a Home Assistant Integration Using ChatGPT

06:26 Wayne Saggers 0 Comments


 

About 10 or so years ago I switched my energy supplier and, as part of the new deal, I got given a smart heating thermostat called a Cosy made by a company called Geo (https://cosy.support.geotogether.com/en/support/solutions/articles/7000011187-introducing-cosy).  It's a decent little bit of kit that can be retrofitted in series with your existing, old-school dumb thermostat.  It simplifies things by giving you three pre-sets: Slumber (for a relatively cool environment to sleep in), Comfy (for when you just want to take the chill off) and Cosy (For full blown get a sweat on do nothing on the sofa type days).  You can set a target temperature for each mode, along with schedules for you want each mode to automatically activate.  It has a nice little app, a web interface if you'd prefer that, and can be controlled to some extent via Alexa.

But I've been a Home Assistant user for quite a few years now, and it's quite nice to be able to control things like heating using triggers other than just time, and it using it via HA would give it a bit more flexibility.  For instance, the Cosy monitors temperature using neat a little portable control device that you can move to different places in your home.  But, in my house at least, the temperature is not always the same in different places it could be cold downstairs but toasty in the bedrooms and , if that's where the Cosy device is, it'll stay cold downstairs.  Sure, I could turn the heating on manually but where would be the fun in that?  By sticking some cheap £2 AliExpress temperature sensors around the house, it would be possible to turn the heating on when any area gets cold, not just where the Cosy happens to be.  Pair that up with some smart radiator thermostats and we can even heat just the area / room that is cold rather than the entire house.  But there was a problem, there was no Home Assistant integration available for Cosy.  Sad times.  

I've built myself a few smart home devices in the past that have used MQTT to let Home Assistant to control them and it's worked pretty well, so a few years ago I created a 'Cosy Server' within a Docker container that combined an MQTT server that could receive commands from HA and send back status updates, with a NodeJS implementation of Puppeteer / headless browser which automated the actions of logging on to the Cosy web front end to scrape the information and switch modes etc. It was a bit of a clunky approach, but it worked OK for a while.  It was also pretty limited: you could change modes and get the current mode but that was about it, and you couldn't set it to Hibernate.  The HA front end controls were also a bit lacklustre, a few switches to change the mode was about the extent of it, but you could automate based on other triggers, so it sort of did the job.  But it wasn't very robust.  It didn't always work, sometimes MQTT messages didn't get sent or received or whatever, the server sometimes stopped working and I never got around to debugging it and then, eventually I moved from a HA installation on top of a full-blown Linux install to a HASS image and so stopped using my little server.  I'd posted about my project on the HA forums, and shared the Github repository just in case it might be useful for anyone else.  It turned out it was.  About a year later someone who had seen my project got inspired to create something similar, rather than use MQTT, they wanted to use If This Then That (IFTT) to allow them to control their heating using outside triggers like emails etc. They went for a NuGet package for C# .NET instead of the Docker / Node route I had taken, but more importantly, they had done it using Cosy's non-public API which is what Cosy's web front end uses, rather than going down the headless browser / scraping route that I'd used.  You can see their project here: https://github.com/dan-agilexp/cosyrest/blob/main/README.md  

Using the API seemed like a much better idea and I'd always thought about creating a proper Home Assistant integration so that I'd have full control of everything (modes, target temperatures, hibernate on / off, etc.)  and also have decent and pretty controls on the Home Assistant front end.  I never got around to it until, three years later, which happens to be a few days ago, I did. 

I don't code much these days, I don't really have the time, but I recently came across a YouTube video where a fella let ChatGPT take control of his smart home through HA's built in voice assistant capability and it looked pretty cool.  I thought about maybe doing something similar, but felt like heating would be a key thing I'd like it to be able to control a bit more dynamically.  I remembered the post from the guy I'd inspired, and in turn his work with the non-public Cosy API inspired me to have a look and see if I could create a Home Assistant integration.  

The first step was to figure out how the API worked.  To do this, I used Chrome's built in developer tools. You can access them by clicking the 3 dot menu button to the right of the address bar, hover over 'More Tools' then click developer tools.  This opens a new section within your browser window, and gives you a bunch of tools that allow you to see how a website has been created.  Along the top there are some tabs such as Elements, Console, etc.  that let you inspect different components of the site.  What I was interested in was the messages being sent to and from the site to control the Cosy system.  Luckily, there's a tab for that too.  It's called Network. I navigated the the login page for the Cosy web front-end, then pressed the record button in the toolbar just below the tabs.  I then logged into Cosy, navigated around and changed settings etc. Once I'd done the main actions I wanted to include, I pressed the stop button next to the record button.  Here's how things looked:


The name column on the left shows the different requests that had been made.  By clicking on these I could see the URL's and headers that had been used to request different actions, I could also see the kinds of JSON responses etc. that came back by looking at the response tab on the right-hand pane.  This gave me all the information I needed to know how to interact with the Cosy API to control the device, and what kind of information it would send me back and therefore how I could parse it to get the useful stuff out.

From that point it was pretty easy to write a little Python script that used the requests library to send the right commands to the Cosy API.  If you've not used requests before, here's a little snippet:


import requests
import argparse

# Cosy API endpoints
base_url = "https://cosy.geotogether.com/api/userapi/"

def get_current_temperature(token,systemID):
    data_url = base_url + "system/cosy-live-data/"+systemID
    try:
        headers = {"Authorization": f"Bearer {token}"}
        response = requests.get(data_url, headers=headers)
        response.raise_for_status()
        data = response.json()
        temperature = data["temperatureList"][0]["value"]
        return temperature
    except requests.exceptions.RequestException as e:
        print(f"Error retrieving temperature: {e}")
        return None

I used argparse to allow me to pass commands to the script (--setmode, --getcurrenttemp, etc.) so that I could
call the different methods to control my Cosy system and get info back. It all worked perfectly.

Now I needed to turn the script into a Home Assistant integration. Now, full disclosure, I'm a hobbyist
programmer these days. I do a bit here and there, but I'm far from a professional developer. I had a look at the
Home Assistant Developer documentation, and quickly realised that I wasn't the target audience 😂. I had a bit
of a crack at creating the relevant manifest.json files and config_flow.py files, but it didn't go too well. I then had
a search around on Google and discovered that I wasn't the only person to find the HA docs challenging. There
were some folks out there that had made some honourable attempts at simpler guides, and they helped me get
closer to the goal, but the context and gaps in their explanations meant that it was challenging to apply what they
were saying to my particular use case. Ideally, I would've spent time learning the ins and outs of what was
required but, to be honest, I didn't have the time and I don't know when I'll use it again so will have probably
forgotten it by the time I do. So I was at a point where my little script was probably going to be a sufficient
achievement, and I could probably get HA to use that to control my Cosy. It wasn't the full integration I wanted,
but it was better and more efficient than the cosy server I built previously.

But then I remembered something. A while back I had a play around with an early version of a GPT that was
being built to create full-stack applications and, whilst it wasn't perfect, it was impressive. So I wondered if I
could use ChatGPT to help me create my integration. I pasted my code into ChatGPT, told it that I wanted to
create an integration for Home Assistant, and asked if it could help me do that. Sure! came the response, and it
proceeded to spit out all the necessary files I needed. I span up a Home Assistant dev environment in visual
studio code:(https://developers.home-assistant.io/docs/development_environment/).
Stuck the files into the custom_components folder, and fired it up, not really expecting it to work. It didn't.
But I could see from the logs in Home Assistant that it was a fairly simple problem. It also needed me to add stuff to configuration.yaml
and I didn't want that, I'd prefer to have it configurable by the UI. I explained the error I'd seen to ChatGPT and explained
the additional requirements I had, and she (I don't know why it ChatGPT feels like a she to me, but it does) gave me a new
version of the files that needed editing. It took a few back-and-forths of her providing me with new versions, and me telling
her about the various errors I'd received, but eventually we got to something that looked like it was almost working. We had
a UI card that at least reported the current temperature, and the entity was logging the temp over time. But there was still a
few errors, and I couldn't set the modes etc. On and off over the next couple of days I described the new features I wanted,
and ChatGPT would give me updated code, I'd try it, and then go back to her with the results. It was often one step forward
and two steps back. She'd give me a new piece of code to fix a problem, but that in turn would break something else. In the
end, I got to a point where it felt like I was going around in circles. There was an issue that would arise with logging in, but
the solution ChatGPT provided would then break my get_temperature method, and the fixes for that would ultimately break
the logon method again. I tried asking for what I wanted in different ways, but it didn't seem to help. Sometimes ChatGPT
would provide me with code as a solution, but when I check it was identical to the previous version.
I decided I needed a new approach.  I realised that what I'd been doing was a bit piecemeal.  I'd started off with a pretty vague request, and ChatGPT had done her best to give me what I wanted.  As I made more and more changes, I think a lot of the context got lost along the way.   I lead Innovation projects for a living, so I understand the importance of giving a developer clear requirements.  I've also used ChatGPT enough to know that giving her a role as part of a prompt typically improves the responses.  So I provided a new prompt:

Ok we seem to just be going around in circles. Lets try a new approach. The file CosyLogin.py is a Python script that I wrote which allows you to control a heating thermostat using their web api. You are a skilled python programmer, I would like to use this script to create a Home Assistant integration. Please can you write all of the files I need to do this. The requirements are as follows:

  1. All settings to install the integration must be accessible from the UI (ie. not using configuration.yaml)
  2. It must have a unique ID so that it can be managed in the UI once installed
  3. It must be able to get both the current temperature and the current preset mode
  4. It must be able to set the current preset mode, these are slumber, comfy and cosy
  5. It must be able to set the target temperature for each of the preset modes
  6. It must allow us to switch hiberate mode on and off
  7. If hibernate mode is on and the user tries to set one of the preset modes, it must first switch hibernate mode off
  8. It must be controllable via a lovelace UI card which shows the current temperature, the current preset mode, and allows the you to set the target temperature for the current preset mode.
Ok we seem to just be going around in circles. Lets try a new approach. The file CosyLogin.py is a Python scriptthat I wrote which allows you to control a heating thermostat using their web api. You are a skilled python  programmer, I would like to use this script to create a Home Assistant integration. Please can you write all of the filesI need to do this.
The requirements are as follows: All settings to install the integration must be accessible from the UI (ie. not using configuration.yaml) It must have a unique ID so that it can be managed in the UI once installed It must be able to get both the current temperature and the current preset mode It must be able to set the current preset mode, these are slumber, comfy and cosy It must be able to set the target temperature for each of the preset modes It must allow us to switch hiberate mode on and off If hibernate mode is on and the user tries to set one of the preset modes, it must first switch hibernate mode off It must be controllable via a lovelace UI card which shows the current temperature, the current preset mode, and
allows
you to set the target temperature for the current preset mode.

ChatGPT came back with:

Sure, let's create a Home Assistant integration based on your CosyLogin.py script. We'll break this down into
several files:
manifest.json - Metadata about the integration.
config_flow.py - Handles the configuration flow for the integration. const.py - Constants used in the integration. api.py - Handles the communication with the Cosy API. climate.py - Defines the climate entity for Home Assistant. __init__.py - Initializes the integration.
And the proceeded to give me the files. Again, I dutifully uploaded them to my HA dev environment and tested them.
There were errors again, but this time we were much closer. We had a UI card with the current and target temperatures,
there were drop-downs with the pre-set and HVAQ modes and it was retrieving live data. We again needed the
back-and-forth around errors in the logs, and I had to remind her of some of the initial requirements. Along the way I'd
picked up bits and pieces about how the HA components worked so I was able to provide better guidance about how issues
might be fixed. I also found that providing text and code examples from the HA documentation as context made things go
much more smoothly. And then, after maybe an hour, I had exactly the integration I had been hoping for. It worked
perfectly and had all the functionality I wanted. I give you geo_cosy:


If, like me, you don't code very often, ChatGPT makes an excellent copilot. It can be frustrating at times, but I
discovered that by following some rules, you can make things much better. Here are some guiding principles that I found
useful:

1. Be clear about what type of developer you want ChatGPT to be
2. Provide clear requirements, tell her exactly what you want and break down the elements
3. Context is important. If an issue might be related to multiple files, give her the code from all of the files as context
4. If the conversation goes on for a while, it can be a good idea to remind ChatGPT of the content of all of your files from
    time to time to ensure she is always taking everything into account in her answers.
5. Give her some help. Sometimes going off to the documentation and providing the information for a certain component
can give you a faster and better solution to an error.
6. Say please and thank you. It's only a matter of time. And I for one welcome our robot overlords.

If you'd like to view the Cosy integration you can do so here:

Have you used ChatGPT to help with your coding?  Has it allowed you to build something you would have had the skill or time to build otherwise?  Let me know in the comments.

0 comments: