Skip to main content

INSTAR MQTTv5 with Python - Client Connection

Guangzhou, China

Adding a Personal TLS Certificate

Generating a Private Certificate Authority

INSTAR Cameras already have a valid CA certificate installed that we can use when we access the MQTT service via the camera's DDNS address (e.g. ab1234.ddns3-instar.de). Alternatively, we can upload our own self-signed certificate.

To do this we will use OpenSSL to generate an X.509 digital certificate that uses the X.509 PKI (short for public key infrastructure) standard. This digital certificate allows us to confirm that a specific public key belongs to the subject included within the certificate. There is an identity that issues the certificate and its details are also included in the certificate.

Create a new directory named mosquitto_certificates enter the folder and run the following OpenSSL commands:

openssl genrsa -out ca.key 2048
openssl req -x509 -new -nodes -key ca.key -sha512 -days 3650 -out ca.crt

Since we will not be verifying the certificate, it does not really matter what you fill out here:

Country Name (2 letter code) [AU]:
State or Province Name (full name) [Some-State]:
Locality Name (eg, city) []:
Organization Name (eg, company) [Internet Widgits Pty Ltd]:INSTAR MQTTv5
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:INSTAR MQTTv5
Email Address []:

After running the previous commands, we will have the following two files in the mqtt_certificates directory:

  • ca.key: Certificate authority key
  • ca.crt: Certificate authority certificate file

Creating a Certificate for the Mosquitto Server

We need generate a new private key and use the key to and generates the server certificate: file

openssl genrsa -out server.key 2048
openssl req -new -key server.key -out server.csr

It does not really matter what you fill out here. Except - you have to set the FQDN to an address/url through which you will be contacting the MQTT service:

Country Name (2 letter code) [AU]:
State or Province Name (full name) [Some-State]:
Locality Name (eg, city) []:
Organization Name (eg, company) [Internet Widgits Pty Ltd]:INSTAR MQTTv5
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:192.168.2.118
Email Address []:

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:

The command generates a server.crt file with the signed X.509 digital certificate for the Mosquitto server:

openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt -days 3650 -sha512
Signature ok
subject=C = AU, ST = Some-State, O = INSTAR MQTTv5, CN = 192.168.2.118
Getting CA Private Key

After running the previous commands, we will have the following 3 new files in the mqtt_certificates directory:

  • server.key: Server key
  • server.csr: Server certificate signing request
  • server.crt: Server certificate file

Upload to your INSTAR Camera

Your INSTAR camera has two expectations that we need to full fill before uploading our certificates:

  1. Combine the server.key and server.crt in a single file server.pem:
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAy/8kPEhDg9rJ3Rb60Vax7pgtUTKLQ0hi1BZl3OBH/JuKmvVO
...
jLeAC8HlqWJMNlm8DWSIGWZSBmgS11Dakw8gGxNJ4UThUwnx2XrnLA==
-----END RSA PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
MIIDKzCCAhMCFArfrELy23ar8AW8OKk5WXn7TLa/MA0GCSqGSIb3DQEBDQUAMFIx
...
PlC3SfWTSo3XJlPjU2xRToRG4rO7oyxN/0X7dGQLCrSJjSJoC3Jeky91EpIouwU=
-----END CERTIFICATE-----
  1. Open the ca.crt and re-save it as ca.pem.

CA Store

Now take the ca.pem and upload it to the INSTAR CA Store:

INSTAR MQTT API Python

Server Certificate

Next, upload the server.pem file as our camera's TLS certificate:

INSTAR MQTT API Python

Don't forget to toggle it on before leaving this menu.

Creating a Certificate for each MQTT Client

Run the following command to create a 2,048-bit client key and the certificate-signing request, also known as CSR:

openssl genrsa -out client.key 2048
openssl req -new -key client.key -out client.csr
Country Name (2 letter code) [AU]:
State or Province Name (full name) [Some-State]:
Locality Name (eg, city) []:
Organization Name (eg, company) [Internet Widgits Pty Ltd]:INSTAR MQTTv5
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:MQTT Client
Email Address []:

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:

The following command then generates a client.crt file with the signed X.509 digital certificate for the MQTT client:

openssl x509 -req -in client.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out client.crt -days 3650 -sha512 -addtrust clientAuth
Signature ok
subject=C = AU, ST = Some-State, O = INSTAR MQTTv5, CN = MQTT Client
Getting CA Private Key

Testing the MQTT TLS Client Authentication

We can now test our certificates, for example, with an graphical MQTT client like the MQTT Explorer. Start by uploading the ca.crt and client.crt + client.key:

INSTAR MQTT API Python

Activate your cameras MQTT Server with TLS encryption:

INSTAR MQTT API Python

And configure the MQTT Explorer with your camera's IP address and MQTT Broker login:

INSTAR MQTT API Python

Hit Connect and you should see your Broker messages as well as your camera's state messages coming in:

INSTAR MQTT API Python

Now with everything set up - Python!

Installing paho-mqtt for Python

Create a dependencies.txt file inside your project folder/venv with the following dependencies:

paho-mqtt==1.6.1

And install them using:

pip install -r dependencies.txt

Connecting a Python Client to our INSTAR MQTT(S)v5 Server

First, we will have to create an MQTT client with paho-mqtt that connects to the INSTAR MQTT server. And the configuration is about the same as the one we needed to connect the MQTT Explorer:

config.py

import os.path
# Replace mosquitto_certificates with the path
# in which you saved the certificate authority file,
# the client certificate file and the client key
certificates_path = "mosquitto_certificates"
ca_certificate = os.path.join(certificates_path, "ca.crt")
client_certificate = os.path.join(certificates_path, "client.crt")
client_key = os.path.join(certificates_path, "client.key")
# Replace 192.168.2.118 with the IP or hostname
# INSTAR IP cameras
# Make sure the IP or hostname matches the value
# you used for Common Name for the certificate
mqtt_server_host = "192.168.2.118"
mqtt_server_port = 8883
mqtt_bind_address = ""
mqtt_bind_port = 0
mqtt_username = "admin"
mqtt_password = "instar"
mqtt_transport = "tcp"
mqtt_keepalive = 60
mqtt_client_id = "mqtt5_client"
mqtt_lwt = "cameras/118/status/testament"

subscription.py

from config import *
import paho.mqtt.client as mqtt
import ssl
import json

def on_connect(client, userdata, flags, rc, properties=None):
if rc==0:
print("INFO :: Connected to MQTT Broker")
client.subscribe(mqtt_lwt, qos=2, options=None, properties=None)
client.connected_flag=True
else:
print("ERROR :: Connection failed:", rc)
client.connected_flag=False

def on_subscribe(client, userdata, mid, granted_qos, properties=None):
print("INFO :: LWT Subscription: {}".format(
granted_qos[0]))

def on_message(client, userdata, msg):
json_object = json.loads(msg.payload)
print("INFO :: Message received. LWT: {}. State: {}".format(
msg.topic,
json_object["val"]))

if __name__ == "__main__":
client = mqtt.Client(client_id = mqtt_client_id, protocol = mqtt.MQTTv5, transport = mqtt_transport)
client.username_pw_set(username = mqtt_username, password = mqtt_password)
client.tls_set(ca_certs = ca_certificate, certfile = client_certificate,
keyfile = client_key, cert_reqs = ssl.CERT_NONE,
tls_version = ssl.PROTOCOL_TLSv1_2)
client.tls_insecure_set(True)
client.connect(host = mqtt_server_host, port = mqtt_server_port,
keepalive = mqtt_keepalive, bind_address = mqtt_bind_address, bind_port = mqtt_bind_port, properties = None)
client.on_connect = on_connect
client.on_subscribe = on_subscribe
client.on_message = on_message
client.loop_forever()
if client.bad_connection_flag:
print("ERROR :: No Connection to Broker")
client.loop_stop()
sys.exit()

We can run the subscription script and restart our camera we can see the LWT (last-will-and-testament) topic value change from alive to dead and back to alive once our client managed to reconnect:

python subscription.py

INFO :: Connected to MQTT Broker
INFO :: LWT Subscription: Granted QoS 2
INFO :: Message received. LWT: cameras/118/status/testament. State: alive
INFO :: Message received. LWT: cameras/118/status/testament. State: dead
INFO :: Connected to MQTT Broker
INFO :: LWT Subscription: Granted QoS 2
INFO :: Message received. LWT: cameras/118/status/testament. State: alive