Search code examples
amazon-web-servicesreact-nativemqttaws-iotaws-iot-core

React Native authentication and Subscribtion with AWS Cognito UserPools


I'm reading some documentation linked below. My goal is to write a React Native application that allows users to authenticate or create an account and subscribe to AWS IoT Core. Currently following the documentation I was able to do the following:

  1. React Native App.jsx displays the 'sign in or create account' form provided by AWS
  2. Users are able to create and account, get a one time code, and Sign into the app
  3. Users who register are showing up in AWS Console Cognito under user pools
  4. registered Users are allowed to Sign in and out.
  5. ESP32 is able to publish messages to AWS IoT Core, visible and coming in
  6. Logs show AWS IoT core MQTT messages are being sent
  7. AWS IoT Core messages are not being received by react native application.
  8. React Native App shows logs "LOG Attempting to subscribe..." and nothing further

https://docs.amplify.aws/lib/auth/emailpassword/q/platform/react-native/ https://ui.docs.amplify.aws/react-native/connected-components/authenticator

Below is my App.jsx file and it seems like I've triple checked permissions, region, Cognito identity pool and my app is still not able to receive messages. I've even ran the command below which is apparently supposed to tie the iot policy with the target. In CloudWatch I am able to see the logs of the ESP32 publishing to the Topic and AWS Pushing messages out, but still app is dry. My AWS IoT policy basically allows for *any *any.

aws iot attach-policy --policy-name myIoTPolicy --target us-east-2:xxxx.xxxxx.xxxxx.x.xxxxx.
import React, { useState, useEffect } from 'react';
import { Button, View, Text, ScrollView } from 'react-native';
import { AWSIoTProvider } from '@aws-amplify/pubsub';
import { Amplify, PubSub } from 'aws-amplify';

import {
  useAuthenticator,
  withAuthenticator,
} from '@aws-amplify/ui-react-native';

import awsconfig from './src/aws-exports';
Amplify.configure(awsconfig);

function SignOutButton() {
  const { signOut } = useAuthenticator();
  return <Button onPress={signOut} title="Sign Out" />;
}

Amplify.addPluggable(new AWSIoTProvider({
  aws_pubsub_region: 'us-east-2',
  aws_pubsub_endpoint: 'wss://xxxxx.xxxxx.xxxxx.xxxxx.amazonaws.com/mqtt',
}));


function App() {
  const [messages, setMessages] = useState<string[]>([]);
  const [error, setError] = useState<string | null>(null);

  useEffect(() => {
    console.log('Attempting to subscribe...');
    const subscription = PubSub.subscribe('xxxx.xxxxx.xxxxx.xxxxx/pub').subscribe({
      next: (data: { value: any }) => {
        console.log('Message received', data);
        if (data.value) {
          setMessages(prevMessages => [...prevMessages, JSON.stringify(data.value)]);
        } else {
          console.error('Received data does not contain a value property');
        }
      },
      error: error => {
        console.error('An error occurred', error);
        setError(error.message);
      },
      complete: () => console.log('Done'),
    });

    return () => {
      console.log('Unsubscribing...');
      subscription.unsubscribe();
    };
  }, []);


  return (
    <View>
    <Text>IoT Messaging</Text>
    <Text>
      New messages from your device(s) that publish to the topic 'xxxx.xxxx.xxxx.xx/pub' will appear below:
    </Text>
    {error && <Text>Error: {error}</Text>}
    <ScrollView>
      {messages.map((msg, index) => (
        <Text key={index}>
          {msg}
        </Text>
      ))}
    </ScrollView>
    <SignOutButton/>
  </View>
  );
}


export default withAuthenticator(App);

any assistance is appreciated.

I've triple checked permissions, region, Cognito identity pool and my app is still not able to receive messages. I've even ran the command below which is apparently supposed to tie the iot policy with the target. In CloudWatch I am able to see the logs of the ESP32 publishing to the Topic and AWS Pushing messages out, but still app is dry. My AWS IoT policy basically allows for *any *any.

aws iot attach-policy --policy-name myIoTPolicy --target us-east-2:xxxx.xxxxx.xxxxx.x.xxxxx.

Solution

  • The useEffect() was causing my problem. using only the below i was able to have json messages come in, I'm not a react expert so I'm not sure why useEffect behaves like this.

    PubSub.subscribe("myTopic").subscribe({
      next: (data) => console.log("Message received", data),
      error: (error) => console.error(error),
      complete: () => console.log("Done"),
    });