1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129: 130: 131: 132: 133: 134: 135: 136: 137: 138: 139: 140: 141: 142: 143: 144:
<?php
declare(strict_types=1);
namespace App\CloudModule\Model;
use DateInterval;
use DateTime;
use Nette;
use Nette\Utils\ArrayHash;
class AzureManager {
use Nette\SmartObject;
private $interfaceName = 'MqttMessagingAzure';
public function createMqttInterface(string $connectionString) {
$this->checkConnectionString($connectionString);
$data = $this->parseConnectionString($connectionString);
$endpoint = $data['HostName'] . '/devices/' . $data['DeviceId'];
$token = $this->generateSasToken($endpoint, $data['SharedAccessKey']);
$interface = [
'Name' => $this->interfaceName,
'Enabled' => true,
'BrokerAddr' => 'ssl://' . $data['HostName'] . ':8883',
'ClientId' => $data['DeviceId'],
'Persistence' => 1,
'Qos' => 0,
'TopicRequest' => 'devices/' . $data['DeviceId'] . '/messages/devicebound/#',
'TopicResponse' => 'devices/' . $data['DeviceId'] . '/messages/events/',
'User' => $data['HostName'] . '/' . $data['DeviceId'],
'Password' => $token,
'EnabledSSL' => true,
'KeepAliveInterval' => 20,
'ConnectTimeout' => 5,
'MinReconnect' => 1,
'MaxReconnect' => 64,
'TrustStore' => '',
'KeyStore' => '',
'PrivateKey' => '',
'PrivateKeyPassword' => '',
'EnabledCipherSuites' => '',
'EnableServerCertAuth' => false
];
return ArrayHash::from($interface);
}
public function createBaseService() {
$baseService = [
'Name' => 'BaseServiceForMQTTAzure',
'Messaging' => $this->interfaceName,
'Serializers' => ['JsonSerializer'],
'Properties' => ['AsyncDpaMessage' => true],
];
return ArrayHash::from($baseService);
}
public function checkConnectionString(string $connectionString) {
$data = $this->parseConnectionString($connectionString);
if (!isset($data['DeviceId']) ||
!isset($data['HostName']) ||
!isset($data['SharedAccessKey'])) {
throw new InvalidConnectionString();
}
}
public function generateSasToken(string $resourceUri, string $signingKey, string $policyName = null, int $expiresInMins = 525600) {
$now = new DateTime();
$expires = new DateInterval('PT' . $expiresInMins . 'M');
$ttl = $now->add($expires)->getTimestamp();
$encodedResourceUri = urlencode($resourceUri);
$toSign = $encodedResourceUri . "\n" . $ttl;
$hmac = hash_hmac('sha256', $toSign, base64_decode($signingKey), true);
$signature = urlencode(base64_encode($hmac));
$token = 'SharedAccessSignature sr=' . $encodedResourceUri . '&sig='
. $signature . '&se=' . $ttl;
if (!empty($policyName)) {
$token .= '$skn=' . $policyName;
}
return $token;
}
public function parseConnectionString(string $connectionString) {
$connection = trim($connectionString, " =\t\n\r\0\x0B");
$data = [];
foreach (explode(';', $connection) as $i) {
$j = explode('=', $i);
$data[$j[0]] = $j[1];
}
return $data;
}
}