Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add MQTT dispatcher #220

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
Open

Add MQTT dispatcher #220

wants to merge 9 commits into from

Conversation

erwin314
Copy link

@erwin314 erwin314 commented Oct 3, 2024

Description

This PR add's a MQTT dispatcher. Sending Tesla EV fleet telemetry (e.g., SoC) to an MQTT broker provides real-time, lightweight, and efficient data streaming. MQTT's publish-subscribe model scales well for growing fleets, enabling seamless integration with IoT platforms and data analytics systems for improved monitoring and management.

Type of change

Please select all options that apply to this change:

  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Bug fix (non-breaking change which fixes an issue)
  • Documentation update

Checklist:

Confirm you have completed the following steps:

  • My code follows the style of this project.
  • I have performed a self-review of my code.
  • I have made corresponding updates to the documentation.
  • I have added/updated unit tests to cover my changes.
  • I have added/updated integration tests to cover my changes.

@iainwhyte
Copy link

OMG, watching intently :)

datastore/mqtt/mqtt.go Outdated Show resolved Hide resolved
datastore/mqtt/mqtt.go Outdated Show resolved Hide resolved
var tokens []pahomqtt.Token

// Publish each field to the relevant topic on the MQTT broker
for key, value := range convertedPayload {
Copy link
Collaborator

Choose a reason for hiding this comment

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

instead of sending each payload attribute individually, why not send it as a single message and keep the implmentation as other datastores?

Copy link
Author

Choose a reason for hiding this comment

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

For MQTT topic structuring, it is important to maintain clarity and scalability, especially when dealing with dynamic datasets such as fleet telemetry and event logs.

Sending individual metrics over MQTT rather than combining them in a single topic has several advantages:

  • Granular control: Individual topics allow for more precise subscription and filtering. Clients can subscribe only to the specific metrics they need, reducing unnecessary network traffic and processing. A Power Exchange (https://pex.energy) will likely subscript to SoC fields, and a Home Assistant (https://www.home-assistant.io/) might subscribe to location data.
  • Easier parsing and debugging: With separate topics, the payload structure for each metric can be simpler and more consistent. This makes parsing and processing easier on the receiving end.
  • Scalability: As the system grows, it's easier to add new metrics without modifying existing payload structures or breaking existing subscribers.
  • Retention policies: MQTT brokers often allow setting different retention policies per topic, giving you more control over how long each metric's data is stored.

Here is a screenshot from MQTT Explorer demonstrating a clear and scalable topic structure:
Screenshot 2024-10-04 at 08 31 15

}

// Only process reliable ACK if no errors were reported
if !publishError {
Copy link
Collaborator

Choose a reason for hiding this comment

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

yeah this is tricky with the things you have correctly set up. you are asking the vehicle to resend the whole data if partial uploads to mqtt failed. I think we should just attempt to send the whole payload

Copy link
Author

Choose a reason for hiding this comment

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

See my comment above which explains why the MQTT topic structure is important. Topics are not the same as raw packets from the car.

datastore/mqtt/mqtt.go Outdated Show resolved Hide resolved
datastore/mqtt/mqtt.go Outdated Show resolved Hide resolved
datastore/mqtt/mqtt_test.go Outdated Show resolved Hide resolved
@erwin314
Copy link
Author

erwin314 commented Oct 7, 2024

The code hase been updated with the issues mentioned in the comments above.

  • There is now support for MQTT topics: metrics, alerts and errors.
  • Other minor changes and fixes.

@erwin314
Copy link
Author

erwin314 commented Oct 9, 2024

Add detailed MQTT README.md explaining architecture, design choices, and configuration

@erwin314 erwin314 requested a review from agbpatro October 9, 2024 08:13
@@ -312,6 +316,17 @@ func (c *Config) ConfigureProducers(airbrakeHandler *airbrake.AirbrakeHandler, l
producers[telemetry.ZMQ] = zmqProducer
}

if _, ok := requiredDispatchers[telemetry.MQTT]; ok {
if c.MQTT == nil {
return nil, errors.New("Expected MQTT to be configured")
Copy link
Collaborator

Choose a reason for hiding this comment

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

golang errors usually starts with lowercase :-

errors.New("expected MQTT to be configured")

Copy link
Author

Choose a reason for hiding this comment

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

All other related errors in the same method use a capital letter:
"Expected ZMQ/Kinesis/PubSub/Kafka/MQTT to be configured"

Maybe it is better if someone creates a separate pull request to fix all error messages?
(and then maybe also have a look at capital letters used in errors.py)

SetKeepAlive(time.Duration(config.KeepAlive) * time.Second)

client := PahoNewClient(opts)
client.Connect()
Copy link
Collaborator

Choose a reason for hiding this comment

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

do we need to do any error handling here?

Copy link
Author

Choose a reason for hiding this comment

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

ConnectRetry is set. So, the client.Connect() might fail, but that's not a problem because the Paho client will keep trying to connect.
This will make sure a telemetry container can start even if a configured MQTT broker is not online.

Sign up for free to 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.

3 participants