Skip to content

Commit d01e25b

Browse files
committed
Added tls example for gateway client
1 parent c930d21 commit d01e25b

File tree

5 files changed

+78
-79
lines changed

5 files changed

+78
-79
lines changed

examples/gateway/DEPRECATEDclaiming_device_pe_only.py

Lines changed: 0 additions & 58 deletions
This file was deleted.

examples/gateway/tls_connect.py

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
# Copyright 2025 ThingsBoard
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
# This example demonstrates how to connect to ThingsBoard over SSL using the GatewayClient,
16+
# connect a device, and send telemetry data securely.
17+
18+
import asyncio
19+
import logging
20+
import random
21+
22+
from tb_mqtt_client.common.config_loader import GatewayConfig
23+
from tb_mqtt_client.common.logging_utils import configure_logging, get_logger
24+
from tb_mqtt_client.entities.data.timeseries_entry import TimeseriesEntry
25+
from tb_mqtt_client.service.gateway.client import GatewayClient
26+
27+
configure_logging()
28+
logger = get_logger(__name__)
29+
logger.setLevel(logging.INFO)
30+
logging.getLogger("tb_mqtt_client").setLevel(logging.INFO)
31+
32+
33+
PLATFORM_HOST = 'localhost' # Update with your ThingsBoard host
34+
PLATFORM_PORT = 8883 # Default port for MQTT over SSL
35+
36+
37+
# Update with your CA certificate, client certificate, and client key paths. There are no default files generated.
38+
# You can generate them using the following guides:
39+
# Certificates for server - https://thingsboard.io/docs/user-guide/mqtt-over-ssl/
40+
# Certificates for client - https://thingsboard.io/docs/user-guide/certificates/?ubuntuThingsboardX509=X509Leaf
41+
CA_CERT_PATH = "mqttserver.pem" # Update with your CA certificate path (Default - mqttserver.pem in the examples directory)
42+
CLIENT_CERT_PATH = "cert.pem" # Update with your client certificate path (Default - cert.pem in the examples directory)
43+
CLIENT_KEY_PATH = "key.pem" # Update with your client key path (Default - key.pem in the examples directory)
44+
45+
46+
async def main():
47+
config = GatewayConfig()
48+
49+
config.host = PLATFORM_HOST
50+
config.port = PLATFORM_PORT
51+
52+
config.ca_cert = CA_CERT_PATH
53+
config.client_cert = CLIENT_CERT_PATH
54+
config.private_key = CLIENT_KEY_PATH
55+
56+
client = GatewayClient(config)
57+
await client.connect()
58+
59+
device_name = "Test Device B1"
60+
device_profile = "Test devices"
61+
logger.info("Connecting device: %s", device_name)
62+
device_session, publish_results = await client.connect_device(device_name, device_profile, wait_for_publish=True)
63+
64+
# Sending telemetry data to the connected device
65+
list_timeseries = [
66+
TimeseriesEntry(key="temperature", value=random.randint(20, 35)),
67+
TimeseriesEntry(key="humidity", value=random.randint(40, 80))
68+
]
69+
logger.info("Sending list of timeseries: %s", list_timeseries)
70+
await client.send_device_timeseries(device_session=device_session, data=list_timeseries, wait_for_publish=True)
71+
logger.info("List of timeseries sent successfully.")
72+
73+
await client.stop()
74+
75+
if __name__ == "__main__":
76+
asyncio.run(main())

tb_mqtt_client/common/config_loader.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,8 @@ def __init__(self, config=None):
100100
if os.getenv("TB_GW_QOS") is not None:
101101
self.qos: int = int(os.getenv("TB_GW_QOS", 1))
102102

103+
104+
103105
def __repr__(self):
104106
return (f"GatewayConfig(host={self.host}, port={self.port}, "
105107
f"auth={'token' if self.access_token else 'user/pass'} "

tb_mqtt_client/service/gateway/client.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -402,10 +402,6 @@ async def _unsubscribe_from_gateway_topics(self):
402402
async def _handle_rate_limit_response(self, response: RPCResponse): # noqa
403403
device_rate_limits_processing_result = await super()._handle_rate_limit_response(response)
404404
try:
405-
if not isinstance(response.result, dict) or 'gatewayRateLimits' not in response.result:
406-
logger.warning("Invalid gateway rate limit response: %r", response)
407-
return None
408-
409405
gateway_rate_limits = response.result.get('gatewayRateLimits', {})
410406

411407
await self._gateway_rate_limiter.message_rate_limit.set_limit(gateway_rate_limits.get('messages', '0:0,'), percentage=DEFAULT_RATE_LIMIT_PERCENTAGE)

tests/service/gateway/test_gateway_client.py

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -484,22 +484,5 @@ async def test_handle_rate_limit_response():
484484
client._mqtt_manager.set_gateway_rate_limits_received.assert_called_once()
485485

486486

487-
@pytest.mark.asyncio
488-
async def test_handle_rate_limit_response_invalid_response():
489-
# Setup
490-
client = GatewayClient()
491-
492-
# Create an invalid response
493-
response = RPCResponse.build(1, result="invalid")
494-
495-
# Mock the parent class method
496-
with patch('tb_mqtt_client.service.device.client.DeviceClient._handle_rate_limit_response', return_value=None):
497-
# Act
498-
result = await client._handle_rate_limit_response(response)
499-
500-
# Assert
501-
assert result is None
502-
503-
504487
if __name__ == '__main__':
505488
pytest.main([__file__])

0 commit comments

Comments
 (0)