AWS IoT proporciona comunicación segura y bidireccional entre dispositivos conectados a Internet, como sensores, actuadores, microcontroladores integrados o electrodomésticos inteligentes, y la nube AWS. Esto le permite recopilar datos de telemetría de múltiples dispositivos, almacenarlos y analizarlos. También puede crear aplicaciones que permitan a sus usuarios controlar estos dispositivos desde sus teléfonos o tabletas.
Proporciona un mecanismo seguro para que los dispositivos y las aplicaciones de AWS IoT publiquen y reciban mensajes entre sí. Puede usar el protocolo MQTT directamente o MQTT sobre WebSocket para publicar y suscribirse.
El agente de mensajes AWS IoT es un servicio de agente de publicación/suscripción que permite el envío y la recepción de mensajes hacia y desde AWS IoT. Al comunicarse con AWS IoT, un cliente envía un mensaje dirigido a un tema como Sensor/temp/room1.
El broker de mensajes, a su vez, envía el mensaje a todos los clientes que se han registrado para recibir mensajes sobre ese topic. El acto de enviar el mensaje se denomina publicación. El acto de registrarse para recibir mensajes sobre un filtro de topic se denomina suscripción.
El espacio de nombres de temas está aislado para cada par de cuenta y región de AWS. Por ejemplo, el tema Sensor/temp/room1 de una cuenta AWS es independiente del tema Sensor/temp/room1 de otra cuenta AWS. Lo mismo ocurre con las regiones. El tema Sensor/temp/room1 en la misma cuenta AWS en us-east-1 es independiente del mismo tema en us-east-2. AWS IoT no admite el envío y la recepción de mensajes entre cuentas y regiones de AWS.
El broker de mensajes mantiene una lista de todas las sesiones de clientes y las suscripciones de cada sesión. Cuando se publica un mensaje en un tema, el broker busca sesiones con suscripciones que coincidan con el tema. A continuación, el broker reenvía el mensaje publicado a todas las sesiones que tienen un cliente conectado actualmente.
TsgcIoTAmazon_MQTT_Client es el componente utilizado para conectarse a AWS IoT. Un cliente solo puede conectarse a un dispositivo. El cliente se conecta mediante el protocolo MQTT estándar y se autentica usando un certificado de cliente X.509.
Para conectarse a AWS IoT, el cliente necesita las siguientes propiedades:
Amazon.ClientId: identificación del cliente, opcional.
Amazon.Endpoint: nombre del servidor al que se conectará el cliente MQTT.
Amazon.Port: por defecto utiliza el puerto 8883. Si el puerto es 443, utiliza ALPN automáticamente para conectarse (requiere versión personalizada de Indy).
AWS IoT Core admite dispositivos y clientes que usan los protocolos MQTT y MQTT sobre WebSocket Secure (WSS) para publicar y suscribirse a mensajes. La siguiente tabla enumera los protocolos que admiten los endpoints de dispositivos de AWS IoT, así como los métodos de autenticación y puertos que utilizan.
| Protocolo | Autenticación | Puerto | Nombre de Protocolo ALPN |
| MQTT over WebSocket | Signature Version 4 | 443 | |
| MQTT over WebSocket | Autenticación personalizada | 443 | |
| MQTT | Certificado de cliente X.509 | 443 | x-amzn-mqtt-ca |
| MQTT | Certificado de cliente X.509 | 8883 | |
| MQTT | Autenticación personalizada | 443 | mqtt |
Necesita crear certificados en su consola de Amazon AWS y establecer la ruta donde están almacenados.
Usando OpenSSL como IOHandler debe establecer el certificado en las siguientes rutas
Certificate.Enabled: establézcalo en True si desea utilizar certificados.
Certificate.CertFile: ruta al certificado de cliente X.509.
Certificate.KeyFile: ruta al archivo de clave de cliente X.509.
Al utilizar SChannel como IOHandler, primero convierta el Certificado PEM + Clave a un certificado PFX. Esto requiere los binarios de OpenSSL:
openssl pkcs12 -inkey 884ccf73ff-private.pem.key -in 884ccf73ff-certificate.pem.crt -export -out 884ccf73ff-certificate.pfx
A continuación, establezca las siguientes rutas (no es necesario establecer el archivo de clave porque ya está incluido en el certificado).
Certificate.Enabled: establézcalo en True si desea utilizar certificados.
Certificate.CertFile: ruta al certificado PFX
Debe crear un usuario en su consola de Amazon AWS y guardar las claves de acceso y secretas, que se utilizarán para firmar la solicitud WebSocket.
SignatureV4.Enabled: establézcalo en True si desea utilizar este tipo de autenticación.
SignatureV4.Region: la región donde se encuentra su dispositivo (ejemplo: us-east-1).
SignatureV4.AccessKey: la clave de acceso creada en su consola de Amazon u obtenida como credencial temporal.
SignatureV4.SecretKey: la clave secreta creada en su consola de Amazon o obtenida como credencial temporal
SignatureV4.SessionToken: (condicional) si utiliza credenciales de seguridad temporales, establezca aquí el token de seguridad.
OpenSSL_Options: configuración de las bibliotecas OpenSSL.
APIVersion: permite definir qué API de OpenSSL se utilizará.
oslAPI_1_0: utiliza API 1.0 de OpenSSL, la última versión compatible con Indy
oslAPI_1_1: utiliza la API 1.1 de OpenSSL, requiere nuestra biblioteca Indy personalizada y permite usar las bibliotecas OpenSSL 1.1.1 (con soporte para TLS 1.3).
oslAPI_3_0: usa la API 3.0 de OpenSSL, requiere nuestra biblioteca Indy personalizada y permite usar las bibliotecas OpenSSL 3.0.0 (con soporte TLS 1.3).
LibPath: aquí puede configurar dónde se encuentran las bibliotecas openSSL
oslpNone: es el valor predeterminado; las bibliotecas openSSL deben estar en la misma carpeta donde se encuentra el binario o en una ruta conocida.
oslpDefaultFolder: establece automáticamente la ruta de openSSL donde deben ubicarse las bibliotecas para todas las personalidades del IDE.
oslpCustomFolder: si esta es la opción seleccionada, defina la ruta completa en la propiedad LibPathCustom.
LibPathCustom: cuando LibPath = oslpCustomFolder, defina aquí la ruta completa donde se encuentran las bibliotecas openSSL.
UnixSymLinks: habilita o deshabilita la carga de SymLinks en sistemas Unix (por defecto está habilitado, excepto en OSX64):
oslsSymLinksDefault: están habilitados por defecto excepto en OSX64 (tras MacOS Monterey, falla al intentar cargar la biblioteca sin versión.).
oslsSymLinksLoadFirst: Cargar los SymLinks antes de intentar cargar las bibliotecas de versión.
oslsSymLinksLoad: Cargar SymLinks después de intentar cargar las bibliotecas de versión.
oslsSymLinksDontLoad: no carga los SymLinks.
*SignatureV4 requiere Indy 10.5.7 o superior
La autenticación personalizada le permite definir cómo autenticar y autorizar a los clientes mediante recursos de autorizador. El dispositivo transmite credenciales en los campos de cabecera de la solicitud o en los parámetros de consulta (para protocolos MQTT sobre WebSockets) o en los campos de nombre de usuario y contraseña del mensaje MQTT CONNECT (para los protocolos MQTT y MQTT sobre WebSockets).
CustomAuthentication.Enabled: establézcalo en True si desea usar este tipo de autenticación.
CustomAuthentication.Parameters: establezca aquí los parámetros de consulta que se pasarán al servidor (por defecto es /mqtt)
CustomAuthentication.Headers: aquí puede incluir los campos de encabezado personalizados.
CustomAuthentication.WebSockets: si se establece en true, la conexión funcionará a través del protocolo WebSocket; de lo contrario, funcionará sobre TCP simple.
MQTTAuthentication.Enabled: si necesita pasar el nombre de usuario y la contraseña en la conexión MQTT, habilite esta propiedad
MQTTAuthentication.Username: nombre de usuario de la conexión MQTT
MQTTAuthentication.Password: secreto de la conexión mqtt.
El cliente puede enviar opcionalmente un ClientId para identificar la conexión del cliente; así, otros clientes pueden suscribirse para recibir una notificación cada vez que este cliente se haya conectado, suscrito, desconectado...
Si no puede conectarse usando el puerto 8883 y usa TCP como transporte (que es el predeterminado), Amazon utiliza la "política de AWS IoT Core" para conceder o denegar autorización a clientes y suscripciones. Probablemente deba autorizar su ID de cliente.
Entre en su consola de Amazon AWS, vaya a IoT Core y acceda al menú «Secure/Policies»; seleccione la política adjunta a su IoT Thing y compruebe al final cómo está configurada la conexión. Ejemplo:
{
"Effect": "Allow",
"Action": [
"iot:Connect"
],
"Resource": [
"arn:aws:iot:us-east-1:222178873557:client/sdk-java",
"arn:aws:iot:us-east-1:222178873557:client/basicPubSub",
"arn:aws:iot:us-east-1:222178873557:client/sdk-nodejs-*"
]
}
Esta configuración significa que solo se permitirá conectarse a los clientes con ID: sdk-java, basicPubSub y sdk-nodejs-*. Modifíquelo según sea necesario e inténtelo de nuevo.
Si aún no funciona, habilite el registro y compruebe en CloudWatch el motivo por el que no puede conectarse.
MQTTHeartBeat: si está habilitado, intenta mantener activa la conexión MQTT enviando un ping cada x segundos.
Interval: número de segundos entre cada ping.
MQTTAuthentication: si está habilitado, incluye en la conexión MQTT el nombre de usuario y la contraseña
UserName: nombre del usuario
Contraseña: cadena secreta
WatchDog: si está habilitado, cuando se detecta una desconexión inesperada, intenta reconectarse al servidor automáticamente.
Interval: segundos antes de los intentos de reconexión.
Attempts: número máximo de intentos de reconexión; cero significa ilimitado.
LogFile: si está habilitado, guarda los mensajes del socket en un archivo de registro (útil para depuración). El acceso al archivo de registro no es seguro para subprocesos si se accede desde varios subprocesos.
Enabled: si está habilitado, cada vez que el socket reciba o envíe un mensaje, este se guardará en un archivo.
FileName: ruta completa al nombre de archivo.
La implementación MQTT de Amazon se basa en MQTT versión 3.1.1 pero se desvía de la especificación de la siguiente manera:
En AWS IoT, suscribirse a un topic con Calidad de Servicio (QoS) 0 significa que un mensaje se entrega cero o más veces. Un mensaje puede entregarse más de una vez. Los mensajes entregados más de una vez pueden enviarse con un identificador de paquete diferente. En estos casos, el indicador DUP no se establece.
AWS IoT no admite la publicación y suscripción con QoS 2. El broker de mensajes de AWS IoT no envía PUBACK ni SUBACK cuando se solicita QoS 2.
Al responder a una solicitud de conexión, el agente de mensajes envía un mensaje CONNACK. Este mensaje contiene un indicador para señalar si la conexión reanuda una sesión anterior. El valor de este indicador puede ser incorrecto si dos clientes MQTT se conectan simultáneamente con el mismo ID de cliente.
Cuando un cliente se suscribe a un tema, puede haber un retraso entre el momento en que el intermediario de mensajes envía un SUBACK y el momento en que el cliente comienza a recibir nuevos mensajes coincidentes.
La especificación MQTT contempla la posibilidad de que el publicador solicite al broker que retenga el último mensaje enviado a un tema y lo envíe a todos los futuros suscriptores. AWS IoT no admite mensajes retenidos. Si se realiza una solicitud para retener mensajes, la conexión se desconecta.
El broker de mensajes utiliza el ID de cliente para identificar a cada cliente. El ID de cliente se transmite desde el cliente al broker de mensajes como parte de la carga útil MQTT. No se permite que dos clientes con el mismo ID de cliente estén conectados simultáneamente al broker de mensajes. Cuando un cliente se conecta al broker de mensajes usando un ID de cliente que ya está siendo utilizado por otro cliente, se envía un mensaje CONNACK a ambos clientes y el cliente actualmente conectado se desconecta.
En raras ocasiones, el broker de mensajes podría reenviar el mismo mensaje PUBLISH lógico con un ID de paquete diferente.
El broker de mensajes no garantiza el orden en que se reciben los mensajes y los ACK.
Primero, debe iniciar sesión en su consola de AWS, registrar un nuevo dispositivo y crear un certificado X.509 para ese dispositivo. Una vez hecho esto, puede crear un nuevo TsgcIoTAmazon_MQTT_Client y conectarse al servidor AWS IoT. Por ejemplo:
oClient := TsgcIoTAmazon_MQTT_Client.Create(nil);
oClient.Amazon.Endpoint := 'a2ohgdjqitsmij-ats.iot.us-west-2.amazonaws.com';
oClient.Amazon.ClientId := 'sgcWebSockets';
oClient.Certificate.CertFile := 'amazon-certificate.pem.crt';
oClient.Certificate.KeyFile := 'amazon-private.pem.key';
oClient.OnMQTTConnect := OnMQTTConnectEvent;
oClient.Active := True;
procedure OnMQTTConnect(Connection: TsgcWSConnection; const Session: Boolean; const ReturnCode: TmqttConnReturnCode);
begin
ShowMessage('Connected to AWS');
end;
El broker de mensajes utiliza temas para enrutar mensajes de los clientes publicadores a los clientes suscriptores. La barra diagonal (/) se utiliza para separar la jerarquía de temas. La siguiente tabla lista los comodines que pueden usarse en el filtro de temas al suscribirse. # Debe ser el último carácter en el tema al que se suscribe. Actúa como comodín al coincidir con el árbol actual y todos sus subárboles.
Por ejemplo, una suscripción a Sensor/# recibe mensajes publicados en Sensor/, Sensor/temp, Sensor/temp/room1, pero no los mensajes publicados en Sensor.
+ Coincide exactamente con un elemento en la jerarquía de temas. Por ejemplo, una suscripción a Sensor/+/room1 recibe mensajes publicados en Sensor/temp/room1, Sensor/moisture/room1, y así sucesivamente.
oClient := TsgcIoTAmazon_MQTT_Client.Create(nil);
...
oClient.OnSubscribe := OnSubscribeEvent;
vPacketIdentifier := oClient.Subscribe('Sensor/moisture/room1');
procedure OnMQTTSubscribe(Connection: TsgcWSConnection; aPacketIdentifier: Word; aCodes: TsgcWSSUBACKS);
begin
if vPacketIdentifier = aPacketIdentifier then
ShowMessage('Subscribed to topic Sensor/moisture/room1');
end;
// Client, can send a message using Publish method.
oClient.Publish('Sensor/moisture/room1', '{"temp"=10}');
// Messages received from server, are dispatched OnMQTTPublishEvent.
// For extended payload access (string, bytes or stream), use OnMQTTPublishEx.
procedure OnMQTTPublish(Connection: TsgcWSConnection; aTopic, aText: string);
begin
DoLog('Received Message: ' + aTopic + ' ' + aText);
end;
Los siguientes métodos se utilizan para suscribirse a topics reservados o publicar en ellos.
Subscribe_ClientConnected(const aClientId: String): AWS IoT publica en este tema cuando un cliente MQTT con el ID de cliente especificado se conecta a AWS IoT
Subscribe_ClientDisconnected(const aClientId: String): AWS IoT publica en este tema cuando un cliente MQTT con el identificador de cliente especificado se desconecta de AWS IoT
Subscribe_ClientSubscribed(const aClientId: String): AWS IoT publica en este tema cuando un cliente MQTT con el ID de cliente especificado se suscribe a un tema MQTT
Subscribe_ClientUnSubscribed(const aClientId: String): AWS IoT publica en este tema cuando un cliente MQTT con el ID de cliente especificado cancela la suscripción a un tema MQTT
Publish_Rule(const aRuleName, aText: String): Un dispositivo o una aplicación publica en este tema para activar reglas directamente
Publish_DeleteShadow(const aThingName, aText: String): Un dispositivo o una aplicación publica en este tema para eliminar una sombra
Subscribe_DeleteShadow(const aThingName: String): Un dispositivo o una aplicación se suscribe a este topic para eliminar una sombra
Subscribe_ShadowDeleted(const aThingName: String): El servicio Device Shadow envía mensajes a este topic cuando se elimina un shadow
Subscribe_ShadowRejected(const aThingName: String): El servicio Device Shadow envía mensajes a este topic cuando se rechaza una solicitud de eliminación de un shadow
Publish_ShadowGet(const aThingName, aText: String): Una aplicación o un dispositivo publica un mensaje vacío en este topic para obtener un shadow
Subscribe_ShadowGet(const aThingName: String): Una aplicación o un dispositivo se suscribe a este topic para obtener un shadow
Subscribe_ShadowGetAccepted(const aThingName: String): El servicio Device Shadow envía mensajes a este tema cuando una solicitud de sombra se realiza correctamente
Subscribe_ShadowGetRejected(const aThingName: String): El servicio Device Shadow envía mensajes a este topic cuando se rechaza una solicitud de sombra
Publish_ShadowUpdate(const aThingName, aText: String): Un objeto o aplicación publica en este tema para actualizar un shadow
Subscribe_ShadowUpdateAccepted(const aThingName: String): El servicio Device Shadow envía mensajes a este tema cuando una actualización se realiza correctamente en un shadow
Subscribe_ShadowUpdateRejected(const aThingName: String): El servicio Device Shadow envía mensajes a este tema cuando se rechaza una actualización de un shadow
Subscribe_ShadowUpdateDelta(const aThingName: String): El servicio Device Shadow envía mensajes a este topic cuando se detecta una diferencia entre las secciones reported y desired de un shadow
Subscribe_ShadowUpdateDocuments(const aThingName: String): AWS IoT publica un documento de estado en este tema cada vez que se realiza correctamente una actualización del shadow
Una sesión persistente representa una conexión continua con un broker de mensajes MQTT. Cuando un cliente se conecta al broker de mensajes de AWS IoT mediante una sesión persistente, el broker guarda todas las suscripciones que el cliente realiza durante la conexión. Cuando el cliente se desconecta, el broker almacena los mensajes QoS 1 no confirmados y los nuevos mensajes QoS 1 publicados en los temas a los que el cliente está suscrito. Cuando el cliente se vuelve a conectar a la sesión persistente, se restablecen todas las suscripciones y todos los mensajes almacenados se envían al cliente a una tasa máxima de 10 mensajes por segundo.
Se crea una sesión persistente MQTT estableciendo el parámetro cleanSession en False en el evento OnMQTTBeforeConnect. Si no existe ninguna sesión para el cliente, se crea una nueva sesión persistente. Si ya existe una sesión para el cliente, se reanuda.
Los dispositivos deben comprobar el atributo Session en el evento OnMQTTConnect para determinar si existe una sesión persistente. Si Session es True, existe una sesión persistente y los mensajes almacenados se entregan al cliente. Si Session es False, no existe ninguna sesión persistente y el cliente debe volver a suscribirse a sus filtros de tema.
Las sesiones persistentes tienen un período de expiración predeterminado de 1 hora. El período de expiración comienza cuando el broker de mensajes detecta que un cliente se desconecta (desconexión MQTT o tiempo de espera agotado). El período de expiración de la sesión persistente puede aumentarse a través del proceso estándar de incremento de límites. Si un cliente no ha reanudado su sesión dentro del período de expiración, la sesión se termina y los mensajes almacenados asociados se descartan. El período de expiración es aproximado; las sesiones pueden persistir hasta 30 minutos más (pero no menos) que la duración configurada.
AWS IoT Core puede funcionar con credenciales temporales obtenidas a través de grupos de identidades; existen 2 tipos de identidades:
Si utiliza credenciales no autenticadas, simplemente adjunte la política en el rol no autenticado creado automáticamente en el menú IAM. Luego configure el cliente estableciendo el Access, la Secret Key y el Token devueltos por el servicio Cognito.
A continuación se muestra un código en .NET para obtener credenciales no autenticadas
CognitoAWSCredentials credentials = new CognitoAWSCredentials(
"us-east-1:cc3c9c48-646d-44ef-bfd5-0c5fb2f0882f", // Identity pool ID
Amazon.RegionEndpoint.USEast1 // Region
);
var identityPoolId = credentials.GetCredentialsAsync();
AmazonCognitoIdentityClient cognitoClient = new AmazonCognitoIdentityClient(
credentials, // the anonymous credentials
Amazon.RegionEndpoint.USEast1 // the Amazon Cognito region
);
GetIdRequest idRequest = new GetIdRequest();
idRequest.AccountId = "222178873557";
idRequest.IdentityPoolId = "us-east-1:cc3c9c48-646d-44ef-bfd5-0c5fb2f0882f";
GetIdResponse idResp = cognitoClient.GetId(idRequest);
string AccessKey = identityPoolId.Result.AccessKey;
string SecretKey = identityPoolId.Result.SecretKey;
string SessionToken = identityPoolId.Result.Token;
string IdentityId = idResp.IdentityId;
Credenciales autenticadas; requiere adjuntar la política en el Rol Autenticado creado automáticamente en el menú IAM y adjuntar la política del usuario en las políticas de AWS IoT Core.
Por lo tanto, cree una nueva política en el menú de políticas de IoT Core y cada vez que un nuevo usuario se autentique, asocie esta política a dicho usuario.
Puede utilizar el siguiente comando de AWS para adjuntar una política o crear una función lambda.
aws iot attach-policy --policy-name PolicyName --target us-east-1:XXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
El servicio Fleet Provisioning admite las siguientes operaciones de la API MQTT:
CreateCertificateFromCsr
Utilice el método CreateCertificateFromCsr pasando el CertificateSigningRequest como parámetro para crear el certificado. Para recibir la respuesta a esta solicitud, suscríbase primero a los siguientes métodos: SubscribeCreateCertificateFromCsrResponse y SubscribeCreateCertificateFromCsrError
CreateKeysAndCertificate
Utilice el método CreateKeysAndCertificate para crear un nuevo certificado y claves. Para recibir la respuesta a esta solicitud, suscríbase primero a los siguientes métodos: SubscribeCreateKeysAndCertificateResponse y SubscribeCreateKeysAndCertificateError
RegisterThing
Use el método RegisterThing para registrar un nuevo thing pasando como parámetro el nombre de la plantilla y el payload en formato JSON. Para recibir la respuesta a esta solicitud, suscríbase primero a los siguientes métodos: SubscribeRegisterThingResponse y SubscribeRegisterThingError.