Skip to content

Create new MQTT notify plugin#2624

Merged
paranoidi merged 24 commits intoFlexget:developfrom
numericOverflow:develop
Aug 30, 2022
Merged

Create new MQTT notify plugin#2624
paranoidi merged 24 commits intoFlexget:developfrom
numericOverflow:develop

Conversation

@numericOverflow
Copy link
Copy Markdown
Contributor

Motivation for changes:

Enable notification to an MQTT broker, because a plugin didn't exist yet to do so

Detailed changes:

  • New MQTT client notify using paho MQTT library
  • Allows user/pass authentication
  • Allows SSL/TLS certificate authentication

Addressed issues:

None

Implemented feature requests:

None, just my own needs so contribute to code base

Config usage if relevant (new plugin or updated schema):

    Example::
      notify:
        entries:
          via:
            - mqtt:
                broker_address: "iot.eclipse.org"
                topic: "flexget/notifications"
                [broker_port: 1883]
                [broker_timeout: 30]
                [broker_transport: ['tcp','websockets'] ]
                [broker_protocol: ['MQTTv31', 'MQTTv311'] ]
                [username: yourUsernameHere]
                [password: yourPasswordHere]
                [enable_encrypted_communication: True/False]
                [certificates:
                    broker_ca_cert: /path/to/pem/encoded/broker_ca_certificate.crt
                    client_cert: /path/to/pem/encoded/client_certificate.crt
                    client_key: /path/to/pem/encoded/client_certificate.key
                    validate_broker_cert: True/False
                    tls_version: ['tlsv1.2', 'tlsv1.1', 'tlsv1', '']
                ]
                [qos: [0,1,2] ]
                [retain: True/False]

Log and/or tests output (preferably both):

Test config (redacted servers)

            - mqtt:
                broker_address: '5.196.95.208'
                topic: 'flexget/notifications/latest'
                broker_port: 1883
                broker_protocol: 'MQTTv31' #the version of the MQTT protocol to use. Use either MQTTv31 or MQTTv311.
                username: 'mqttclient3'
                password: 'password'
                qos: 1
                retain: True        
            - mqtt:
                broker_address: "mqtt.domain.com"
                topic: "flexget/notifications/latest"
                broker_port: 8883
                certificates: 
                    broker_ca_cert: "C:/Users/User1/Documents/mqtt_test_certs/test_intermediateCA.ca.chain.crt"
                    client_cert: "C:/Users/User1/Documents/mqtt_test_certs/mqttclient3.local.crt"
                    client_key: "C:/Users/User1/Documents/mqtt_test_certs/mqttclient3.local.key"
                    validate_broker_cert: False
                qos: 1
                retain: True
            - mqtt:
                broker_address: "mqtt.domain.com"
                topic: "flexget/notifications/by_series/{% if series_name is defined %}{{series_name}}{% endif %}/{% if ((series_season is defined) and (series_season is number)) %}S{{ '%02d' % series_season }}{% endif %}{% if ((series_episode is defined) and (series_episode is number)) %}E{{ '%02d' % series_episode }}{% endif %}"
                broker_port: 8883
                certificates: 
                    broker_ca_cert: "C:/Users/User1/Documents/mqtt_test_certs/test_intermediateCA.ca.chain.crt"
                    client_cert: "C:/Users/User1/Documents/mqtt_test_certs/mqttclient3.local.crt"
                    client_key: "C:/Users/User1/Documents/mqtt_test_certs/mqttclient3.local.key"
                    validate_broker_cert: False
                qos: 1
                retain: True
            - mqtt:
                broker_address: "mqtt.domain.com"
                topic: "flexget/notifications/by_timestamp/{{now.strftime('%Y.%m.%d_%H.%M.%S')}}/{% if series_name is defined %}{{series_name}}{% endif %} {% if ((series_season is defined) and (series_season is number)) %}S{{ '%02d' % series_season }}{% endif %}{% if ((series_episode is defined) and (series_episode is number)) %}E{{ '%02d' % series_episode }}{% endif %}"
                broker_port: 8883
                certificates: 
                    broker_ca_cert: "C:/Users/User1/Documents/mqtt_test_certs/test_intermediateCA.ca.chain.crt"
                    client_cert: "C:/Users/User1/Documents/mqtt_test_certs/mqttclient3.local.crt"
                    client_key: "C:/Users/User1/Documents/mqtt_test_certs/mqttclient3.local.key"
                    validate_broker_cert: False
                qos: 1
                retain: True                

Log file output (redacted servers a bit)

020-03-13 16:27:21 VERBOSE  mqtt          task_trakt_shows Credential passwords s are redacted to protect the innocent...
020-03-13 16:27:21 VERBOSE  mqtt          task_trakt_shows Auth credentials: username=[mqttclient3] password sha256 hash is "0b14d501a594442a01c6859541bcb3e816d183d32937b851835442f69d5c94e"
020-03-13 16:27:21 VERBOSE  mqtt          task_trakt_shows You can validate them yourself by calculating the sha256 hex digest of your password string (google is your friend if you do not know how to do this)
020-03-13 16:27:21 VERBOSE  mqtt          task_trakt_shows Note: a password that is not provided (i.e. blank) will hash to "e3b0c44298fc1c149afbf4c8996fb92427a41e4649b934ca495991b7852b855"
020-03-13 16:27:21 VERBOSE  mqtt          task_trakt_shows Connecting to 5.196.95.208:1883
020-03-13 16:27:21 VERBOSE  mqtt          task_trakt_shows Sending CONNECT (u0, p0, wr0, wq0, wf0, c1, k30) client_id=b''
020-03-13 16:27:21 VERBOSE  mqtt          task_trakt_shows Connected to MQTT broker
020-03-13 16:27:21 VERBOSE  mqtt          task_trakt_shows Publishing message [Episode Aired: S99E01   {Series Title Redacted} - Episode Title:   {Episode Title Redacted} air date:               2020.03.08] to topic [aewadafsfe/latest]
020-03-13 16:27:21 VERBOSE  mqtt          task_trakt_shows Sending PUBLISH (d0, q1, r1, m1), 'b'flexget/notifications/latest'', ... (100 bytes)
020-03-13 16:27:21 VERBOSE  mqtt          task_trakt_shows Notification sent to broker, waiting for callback response to confirm publishing success - rc=(0, 1)
020-03-13 16:27:21 VERBOSE  mqtt          task_trakt_shows Received CONNACK (0, 0)
020-03-13 16:27:21 VERBOSE  notify        task_trakt_shows Successfully sent a notification to `mqtt`
020-03-13 16:27:21 VERBOSE  mqtt                          Received PUBACK (Mid: 1)
020-03-13 16:27:21 VERBOSE  mqtt          task_trakt_shows TLS version is _SSLMethod.PROTOCOL_TLSv1_2
020-03-13 16:27:21 VERBOSE  mqtt                          MQTT on_publish callback -  message was successfully published to broker as messageID=1
020-03-13 16:27:21 VERBOSE  mqtt          task_trakt_shows TLS cert_required=VerifyMode.CERT_NONE
020-03-13 16:27:21 VERBOSE  mqtt                          Sending DISCONNECT
020-03-13 16:27:21 VERBOSE  mqtt                          MQTT on_disconnect callback - disconnected with result code 0 [Connection Accepted]
020-03-13 16:27:21 VERBOSE  mqtt          task_trakt_shows Connecting to mqtt.domain.com:8883
020-03-13 16:27:21 VERBOSE  mqtt          task_trakt_shows Sending CONNECT (u0, p0, wr0, wq0, wf0, c1, k30) client_id=b'4WaybXA3OXZWt7JxbbY3g9'
020-03-13 16:27:21 VERBOSE  mqtt          task_trakt_shows Connected to MQTT broker
020-03-13 16:27:21 VERBOSE  mqtt          task_trakt_shows Publishing message [Episode Aired: S99E01   {Series Title Redacted} - Episode Title:   {Episode Title Redacted} air date:               2020.03.08] to topic [flexget/notifications/latest]
020-03-13 16:27:21 VERBOSE  mqtt          task_trakt_shows Sending PUBLISH (d0, q1, r1, m1), 'b'flexget/notifications/latest'', ... (100 bytes)
020-03-13 16:27:21 VERBOSE  mqtt          task_trakt_shows Notification sent to broker, waiting for callback response to confirm publishing success - rc=(0, 1)
020-03-13 16:27:21 VERBOSE  mqtt          task_trakt_shows Received CONNACK (0, 0)
020-03-13 16:27:21 VERBOSE  notify        task_trakt_shows Successfully sent a notification to `mqtt`
020-03-13 16:27:21 VERBOSE  mqtt                          Received PUBACK (Mid: 1)
020-03-13 16:27:21 VERBOSE  mqtt          task_trakt_shows TLS version is _SSLMethod.PROTOCOL_TLSv1_2
020-03-13 16:27:21 VERBOSE  mqtt          task_trakt_shows TLS cert_required=VerifyMode.CERT_NONE
020-03-13 16:27:21 VERBOSE  mqtt                          MQTT on_publish callback -  message was successfully published to broker as messageID=1
020-03-13 16:27:21 VERBOSE  mqtt          task_trakt_shows Connecting to mqtt.domain.com:8883
020-03-13 16:27:21 VERBOSE  mqtt                          Sending DISCONNECT
020-03-13 16:27:21 VERBOSE  mqtt                          MQTT on_disconnect callback - disconnected with result code 0 [Connection Accepted]
020-03-13 16:27:21 VERBOSE  mqtt          task_trakt_shows Sending CONNECT (u0, p0, wr0, wq0, wf0, c1, k30) client_id=b'5jIiSJc06SepuskMjpidGA'
020-03-13 16:27:21 VERBOSE  mqtt          task_trakt_shows Connected to MQTT broker
020-03-13 16:27:21 VERBOSE  mqtt          task_trakt_shows Publishing message [Episode Aired: S99E01   {Series Title Redacted} - Episode Title:   {Episode Title Redacted} air date:               2020.03.08] to topic [flexget/notifications/by_series/{Series Title Redacted}/S99E01]
020-03-13 16:27:21 VERBOSE  mqtt          task_trakt_shows Sending PUBLISH (d0, q1, r1, m1), 'b"flexget/notifications/by_series/{Series Title Redacted}/S99E01"', ... (10 bytes)
020-03-13 16:27:21 VERBOSE  mqtt          task_trakt_shows Notification sent to broker, waiting for callback response to confirm publishing success - rc=(0, 1)
020-03-13 16:27:21 VERBOSE  mqtt          task_trakt_shows Received CONNACK (0, 0)
020-03-13 16:27:21 VERBOSE  notify        task_trakt_shows Successfully sent a notification to `mqtt`
020-03-13 16:27:21 VERBOSE  mqtt                          Received PUBACK (Mid: 1)
020-03-13 16:27:21 VERBOSE  mqtt          task_trakt_shows TLS version is _SSLMethod.PROTOCOL_TLSv1_2
020-03-13 16:27:21 VERBOSE  mqtt                          MQTT on_publish callback -  message was successfully published to broker as messageID=1
020-03-13 16:27:21 VERBOSE  mqtt          task_trakt_shows TLS cert_required=VerifyMode.CERT_NONE
020-03-13 16:27:22 VERBOSE  mqtt                          Sending DISCONNECT
020-03-13 16:27:22 VERBOSE  mqtt          task_trakt_shows Connecting to mqtt.domain.com:8883
020-03-13 16:27:22 VERBOSE  mqtt                          MQTT on_disconnect callback - disconnected with result code 0 [Connection Accepted]
020-03-13 16:27:22 VERBOSE  mqtt          task_trakt_shows Sending CONNECT (u0, p0, wr0, wq0, wf0, c1, k30) client_id=b'4I34j21VA4XARV8uos2Gyu'
020-03-13 16:27:22 VERBOSE  mqtt          task_trakt_shows Connected to MQTT broker
020-03-13 16:27:22 VERBOSE  mqtt          task_trakt_shows Publishing message [Episode Aired: S99E01   {Series Title Redacted} - Episode Title:   {Episode Title Redacted} air date:               2020.03.08] to topic [flexget/notifications/by_timestamp/2020.03.13_16.27.21/{Series Title Redacted} S99E01]
020-03-13 16:27:22 VERBOSE  mqtt          task_trakt_shows Sending PUBLISH (d0, q1, r1, m1), 'b"flexget/notifications/by_timestamp/2099.01.01_01.01.01/{Series Title Redacted} S99E01"', ... (100 bytes)
020-03-13 16:27:22 VERBOSE  mqtt          task_trakt_shows Notification sent to broker, waiting for callback response to confirm publishing success - rc=(0, 1)
020-03-13 16:27:22 VERBOSE  mqtt          task_trakt_shows Received CONNACK (0, 0)
020-03-13 16:27:22 VERBOSE  notify        task_trakt_shows Successfully sent a notification to `mqtt`
020-03-13 16:27:22 VERBOSE  mqtt                          Received PUBACK (Mid: 1)
020-03-13 16:27:22 VERBOSE  mqtt                          MQTT on_publish callback -  message was successfully published to broker as messageID=1
020-03-13 16:27:22 VERBOSE  mqtt                          Sending DISCONNECT
020-03-13 16:27:22 VERBOSE  mqtt                          MQTT on_disconnect callback - disconnected with result code 0 [Connection Accepted]

To Do:

  • More validation with other brokers?
  • Current code is non-blocking, but there's an option to make the MQTT publishing calls blocking. input on which method to use?
  • Tweak code to fit project as needed/suggested by maintainers

numericOverflow and others added 2 commits March 9, 2020 10:41
Copy link
Copy Markdown
Member

@liiight liiight left a comment

Choose a reason for hiding this comment

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

Thanks for this! A few changed requested

Copy link
Copy Markdown
Member

@liiight liiight left a comment

Choose a reason for hiding this comment

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

Please install pre-commit as we use it for a bunch of auto style and import order formatting

Copy link
Copy Markdown
Contributor

@ianstalk ianstalk left a comment

Choose a reason for hiding this comment

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

Cool idea, and the code looks pretty good too!

@numericOverflow
Copy link
Copy Markdown
Contributor Author

@liiight - Sorry I disappeared for so long. Figured I should finally clean this up and merge to project. I think I've addressed all the requests, let me know if there's other issues/suggestions you want me to address.

@paranoidi
Copy link
Copy Markdown
Member

@liiight - Sorry I disappeared for so long. Figured I should finally clean this up and merge to project. I think I've addressed all the requests, let me know if there's other issues/suggestions you want me to address.

just couple cleanups, welcome back :)

Copy link
Copy Markdown
Contributor Author

@numericOverflow numericOverflow left a comment

Choose a reason for hiding this comment

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

Comments have been addressed with a couple additional commits

@numericOverflow
Copy link
Copy Markdown
Contributor Author

@paranoidi - requested changes made

@liiight
Copy link
Copy Markdown
Member

liiight commented Feb 22, 2021

@paranoidi LGTM

publish_info,
)
except Exception as e:
raise PluginWarning(f'Error publishing to MQTT broker: {e}')
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Should probably use log.exception .. this catches everything unknown and with this we don't get proper tracebacks.

@paranoidi
Copy link
Copy Markdown
Member

@paranoidi LGTM

Yeah, just one thing about error logging caught my eye. Other than that. Seems good!

@numericOverflow thanks!

@soloam
Copy link
Copy Markdown
Contributor

soloam commented Apr 20, 2021

Looking forward for this plugin

tls_version: ['tlsv1.2', 'tlsv1.1', 'tlsv1']
]
[qos: [0,1,2] ]
[retain: True/False]
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

We use yes/no in yaml as it is more natural language.

'client_cert': {'type': 'string'},
'client_key': {'type': 'string'},
'validate_broker_cert': {'type': 'boolean', 'default': True},
'tls_version': {'type': 'string', 'enum': ['tlsv1.2', 'tlsv1.1', 'tlsv1', '']},
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Why is empty string allowed?

logger.debug('TLS secure cert mode enabled. Broker cert will be validated')

# Handle user/pass authentication
if config.get('username'):
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

When checking key presence in dict the pythonic way is if "username" in config:, same applies to few other places in the code.

@github-actions
Copy link
Copy Markdown
Contributor

This PR is stale because it has been open 150 days with no activity. Remove stale label or comment or this will be closed in 60 days.

@github-actions github-actions bot added the Stale label Sep 18, 2021
@paranoidi paranoidi removed the Stale label Sep 21, 2021
@github-actions
Copy link
Copy Markdown
Contributor

This PR is stale because it has been open 150 days with no activity. Remove stale label or comment or this will be closed in 60 days.

@github-actions github-actions bot added the Stale label Feb 18, 2022
@numericOverflow
Copy link
Copy Markdown
Contributor Author

not stale, TODO eventually

@github-actions github-actions bot removed the Stale label Mar 30, 2022
@github-actions
Copy link
Copy Markdown
Contributor

This PR is stale because it has been open 150 days with no activity. Remove stale label or comment or this will be closed in 60 days.

@github-actions github-actions bot added the Stale label Aug 27, 2022
@paranoidi
Copy link
Copy Markdown
Member

Let's merge this in, it's been pending too long.

@paranoidi paranoidi merged commit 67c68ca into Flexget:develop Aug 30, 2022
@paranoidi
Copy link
Copy Markdown
Member

Awesome job, sorry it took so long to merge this

@paranoidi
Copy link
Copy Markdown
Member

Maybe I spoke too soon, it doesn't seem to work.

@numericOverflow Issue #3533

Can you help a bit with that?

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants