A Home Assistant + MQTT integration for Pulse Hubs

I wrote a AppDaemon (AD) app that lets you bring your Pulse Hub connected devices into Home Assistant (HA) as proper registered entities. It uses MQTT multi-component device discovery in Home Assistant, to register each Pulse API-discovered hub and connected sensor devices with HA.

It uses two scheduled AD jobs to get and publish state updates every minute (configurable) and to discover topology changes every hour (also configurable). Newly connected hubs and devices will be discovered and added to HA, automatically. If a sensor is moved to a different hub, it should follow it in HA within an hour.

Using this, devices on your local network will be able to subscribe to a topic for your Pulse Hub sensor devices, to opt-in for state updates, without having to communicate with the cloud directly. It lets your Hub devices essentially act as if they were intended for MQTT and HA.

I did this because I want to leverage my water content and other measurements in HA automations and I found the existing OpenSprinkler integration lacking in complexity to do the things I need. Hopefully this is not considered self advertising, as I just want others to not have to reinvent the wheel like I did, and to have others to test the code and suggest improvements.

The Github repo is here, feel free to ask questions: https://github.com/terpasaurus-midwest/pulse-sensors-appdaemon

I will make the readme and project structure more clear on how to take this and utilize it in the coming weeks, for anyone not really savvy enough with HA and AD to get going without help. For those who are, you should already have enough info to get going.

3 Likes

Just wanted to say - this is impressive and appreciated :slight_smile:

1 Like

Wow! Thank you. I’ll also look into supporting the Pulse Pro as well (I’m assuming that they have to be managed differently). I might be interested in looking into implementing historic data import. Do you have other things you are interested on your want list? One thing I will need is raw spectrometer data.

BTW, do you prefer a fork->branch->PR or a straight branch->PR workflow?

1 Like

I missed your comment about having to manage a Pulse Pro differently in my initial reply, so I’ve rewritten this to focus on what needs to happen to make things work with a Pulse Pro. And I took a moment to look at the Pulse OpenAPI spec again, to see what data from a Pulse Pro looks like. This should be pretty easy to deal with.

I think it should only be different in minor ways. For a Pulse Pro, device registration should happen the same as for a hub sensor device, like a THV sensor for example. Except, since it has no hub, we would need to not assign a via_device key to the device discovery payload here.

While on this subject, this via_device key is only used so a dashboard template (or whatever) can have context about what hub a sensor is connected to right now, if it wants to group sensors by hub, etc. That’s the only reason I even bother registering a hub device with an essentially dummy sensor component. It makes things cleaner in the HA UI model and more consistent with Pulse’s reality.

Going further up that method, I see we get recent data from the sensor first. Looking at the Pulse API spec, I looks like the Pulse Pro uses a different recent-data endpoint:

https://api.pulsegrow.com/devices/{deviceId}/recent-data

Where the Pulse Hub sensors use:

https://api.pulsegrow.com/sensors/{sensorId}/recent-data

The data model used by the /devices/{}/recent-data endpoint is different than the hub sensors. So we would need a Pydantic model describing the expected schema from the API spec here. And then also a Pydantic model for this All Device Details endpoint, which would be the equivalent to the “get hub details” endpoint for Pulse Hubs.

However, I’ve found the API spec can be wrong sometimes, which is why I prefer to reply on captures of the actual API responses. I didn’t have time to open a ticket to report issues in their OpenAPI spec file yet, and I imagine John would like a week not having to see an email from me, so:

If you could pull a copy of a real response from these above Pulse Pro /devices/{}/recent-data and /devices/details endpoints, as a JSON file, that would be super helpful and should allow me to perform the bulk of this work to support a Pulse Pro device myself in a PR branch up front. Then, you can probably take that and easily finish it from there, if there’s anything missing. If you’re open to that?

If so, you can email me the JSON files here (or make an issue on Github and attach them would be smart, actually) and I will let you know when I have the initial big changes needed, then it should be trivial to bring it to the finish line from there.

Thanks for your comment and appreciation. I like my Pulse Hub and my VWC sensor and hope people that are doing the home DIY thing can use this to get more value out of their Pulse gear :smiley:

Genuinely appreciative that you folks even provide an API to make all of this possible in the first place. I couldn’t make this without it. I have other gear with cloud dependencies that don’t, and my data is forever locked away in their ecosystem. That stuff eventually gets replaced, if I can’t orchestrate it.

I actually had an issue to report on the developer experience front, as a first time user of your API service. I’ll send you a more detailed report via email though. But the TLDR is the OpenAPI spec/Swagger file can use some testing love. I assume you’re like many of us and this file is largely an afterthought for docs generation, and so I’m empathetic to the situation.

However, ideally, you want that file in a state where it can be imported into common tooling devs use when exploring/working with new REST APIs. For example: with openapi-python-client [link], I could take your OpenAPI Swagger file and generate a full Python client for it, with request methods and Pydantic request/response models for validation.

But it needs the Swagger file to be formatted correctly, and it wasn’t when I last tried. As a result, everything in this file I had to make largely by hand and with AI agent support (feeding it docs and API responses). There are similar Swagger-based interface generators for every common language, so resolving it would be a win beyond just Python devs.

It was a month ago, so I need to do things again and then I’ll send you the details. It’s probably a trivial fix on your end, but it would’ve saved me time and reduced code complexity in my app if I could make use of your Swagger file. It also helps with maintenance, since I can adapt to changes in your released API by importing and regenerating your Swagger file on my end.

I just got the pulsegrow-pro a couple of days ago, and just starting to play with it. As for experience with Python, I have taught sections of NASA Goddard’s Python Bootcamp in the past. That said, 4 or 5 of the past 6 years was spent working on the air-gapped GOES-R ground system, maintaining the L2 science products. So, much of my Python is a little out of date, but I can catch up quickly when sufficiently motivated :wink:

In most of my work I was forbidden to use AI tools, so those are mostly new to me. As we move this along, I might ask for some suggestions on how to get them to work without seriously hallucinating – I poked at them a few times at home to see what they could do, and found it was hallucinating so badly that the results were decent suggestions at best.

I’ll try to set things up to collect the endpoints and other device info. This will take me a little while, as I am working on a few other things (like job applications after basically getting DOGE’d).

This looks fun!

1 Like

Sorry to hear about your (presumably) STEM work being impacted. A close friend of mine is a director for a national STEM education thing and her org has been similarly impacted in deep ways. Your Python bootcamp work is awesome. I have no idea how to get into that sort of work, but it sounds extremely rewarding and fun. My lack of a 4 year degree can hold me back into those careers typically held by academics. My learning has been non-traditional/teaching myself while being tossed in the deep end at various jobs over the last 2 decades. I’ve been looking for a change to something more “meaningful” like that, just very slowly since I’m relatively happy with my current role and have plenty to do.

Given you sound good on the Python front, I assume the only thing you might run into friction would be the Poetry stuff, because Python packaging remains a nightmare, as I’m sure it was when you last interacted with it. Or some of the abstract AppDaemon shenanigans, I found confusing while learning. If you run into any annoying blockers there, please don’t hesitate to ping me.

The AI stuff, I don’t use it heavily here but it can be useful. I use it as a productivity enhancer and to teach myself new topics faster than I could in the days without good LLMs. I tend to feed way more context in my prompts than I see others do, which might be how I get more effective results. I hate not being able to articulate better how I get results, as it makes it feel magical when I’m sure it’s not. But I can share some actual prompts I’ve used before on things I’m working on as an example, via email or something.

most of my work I was forbidden to use AI tools, so those are mostly new to me

I did hear that Anthropic released a Claude model that has been approved for work in US classified environments on national security workloads. It sounds like times may be slowly changing there.

In the case of this project, I feed a lot of context to ChatGPT’s Codex tool using the AGENTS.md. It’s the first thing Codex will look to for initial context and instructions for this. And behind the scenes in OpenAI’s configuration for Codex, I configure secrets and other stuff in its runtime environment variables. That way, it can do things for me like I asked you for earlier. I can say, “I’ve armed you with the needed info to connect to the Pulse API, now connect to these endpoints I’m going to paste, using my device info, and make a PR with the captured JSON output from each, in a way that is consistent with the existing mock JSON files.” And it was able to do that without any further exposition from me.

Now that I have a decent, working base on this project, Codex can be really helpful doing major refactoring without breaking the program. I’ve found more abstract or cute ways of doing things as I reach the edges of this or that engineering approach in AppDaemon’s framework, and explaining to Codex this is how I do things now and here’s a quick sketch out of how I want things to be refactored, it does a pretty good job filling in the blanks close to how I would’ve. Then I can just pull its branch, do some fixups, squash some commits, and I have a solid refactor.

Hopefully that gives some helpful perspective. Feel free to follow up with any questions, of course.

1 Like

My company has been really pushing the use of AI tools. I’ve been using it to for test case/unit test generation, small bug fixes, and refactoring. I can be a real time saver for small stuff. Recently for personal use I’ve been trying to learn React using Cursor AI. I’ve managed to build a really fun front end that displays all my data from Pulse devices. I tried to mimic the design of the Apollo command module from NASA. Its powered off a python server that fetches data every minute, stores it in a database, and provides an API for a front end.

2 Likes

I love that! I’ve been a fan of Apollo era stuff ever since I saw Apollo 13 as a child. In 2016, I was able to see the Saturn V rocket in person they have on display at Johnson Space Center in Houston and get in the Apollo 17 command module, among other neat experiences. No doubt @EBo has much cooler anecdotes on the NASA front, though.

I’ve heard Cursor mentioned by some coworkers but haven’t tried it yet. It’s on my list. I only just started making use of Codex and running Ollama and Open WebUI locally.

1 Like

@terpasaurus.midwest Finally had a chance to look into this thread today.

In regards to the api stuff, I gave it a brief glance and it appears to be fine.
I don’t recall us having any complaints either.

However, I’m more than eager to accommodate any requested changes / double check for any issues.
If you have the time - please dm or email us with more details on what’s giving you trouble and I’ll have it sorted.

Also - if you need any new api endpoints, i can usually add them in pretty quickly.

2 Likes

Thanks for the reply. I haven’t had a chance yet to follow-up to reproduce the issue. I’ll do that this week and get back to you via email.

When it comes to new API endpoints, I have some unsolicited suggestions:

  • A single endpoint to fetch recent data of all devices and hubs+sensors would be really nice. Similar to the all-devices call the webapp uses.
  • A single endpoint to fetch all sensors recent data. For when all-devices isn’t needed
  • A single endpoint to fetch all devices recent data (pulse one, pro, zero). Again for when we don’t need everything.
  • A force-read endpoint for sensors would be great. Similar to the “Rapid” button that was graciously added.
  • ability to edit and enable/disable alert thresholds for devices and sensors
  • An endpoint for creating/editing OpenSprinker automation programs

Thank you for the feedback.
i can definitely add in the endpoints for getting data.
I should be able to add that pretty soon.

As for disabling the alert thresholds and editing the sprinkler programs - This is something that I can’t promise. Our public Api uses api-keys and it’s considered a bad practice to use them for anything else than fetching data.
Irrigation comes with a lot of responsibility and we’d like to avoid any risks here.

whoa, wait, where is this “rapid” button?

It’s under the chart where the share and export buttons are.
Only for hub sensors atm.

Hi there, I added two endpoints to the public api.
force-read for the force-read.
And All-Devices for getting the all device data including their most recent datapoint.
The Hubs, Sensors and Ones/ Zeroes/ Pros are all separated in the response, so I didn’t see much sense adding more endpoints. (this won’t affect performance since it’s all cached)