无法在 flutter 中打开 .pem 文件
Unable to open .pem file in flutter
我是编程初学者,我正在为一个学校项目构建一个 android 应用程序以使用 esp 32 和 AWS IOT 来打开 on/off LED。我正在使用 mqtt_client 9.6.4,当我 运行 aws_iot.dart 示例时,我能够连接到 AWS IOT 并使用相同的脚本执行操作。当我在 flutter 中使用相同的代码时,我在调试控制台中收到以下错误消息,E/flutter (15280): [ERROR:flutter/lib/ui/ui_dart_state.cc(209)] Unhandled Exception: FileSystemException: Cannot open文件,路径 = 'AmazonRootCA1.pem'(OS 错误:没有这样的文件或目录,errno = 2)
如何解决?
import 'dart:async';
import 'dart:io';
import 'dart:typed_data';
import 'package:flutter/services.dart';
import 'lib/mqtt_server_client.dart';
import 'lib/mqtt_client.dart';
import 'package:pem/pem.dart';
var switch1 = 0;
Future<int> main() async {
const url = 'xxxxxxxxxxxxxxxx.amazonaws.com';
const port = 8883;
const clientId = 'Flutter';
final client = MqttServerClient.withPort(url, clientId, port);
client.secure = true;
client.keepAlivePeriod = 20;
client.setProtocolV311();
client.logging(on: true);
final context = SecurityContext.defaultContext;
context.setClientAuthorities('AmazonRootCA1.pem');
context.useCertificateChain('certificate.pem.crt');
context.usePrivateKey('private.pem.key');
client.securityContext = context;
final connMess =
MqttConnectMessage().withClientIdentifier(clientId).startClean();
client.connectionMessage = connMess;
try {
print('MQTT client connecting to AWS IoT....');
await client.connect();
} on Exception catch (e) {
print('MQTT client exception - $e');
client.disconnect();
}
if (client.connectionStatus!.state == MqttConnectionState.connected) {
print('MQTT client connected to AWS IoT');
const topic = 'esp32/relay1';
const topic2 = 'esp32/relay2';
final builder = MqttClientPayloadBuilder();
builder.addString('{\"status\":\"0\"}');
client.publishMessage(topic, MqttQos.atLeastOnce, builder.payload!);
client.subscribe(topic2, MqttQos.atLeastOnce);
client.updates!.listen((List<MqttReceivedMessage<MqttMessage>> c) {
final recMess = c[0].payload as MqttPublishMessage;
final pt =
MqttPublishPayload.bytesToStringAsString(recMess.payload.message);
print(
'EXAMPLE::Change notification:: topic is <${c[0].topic}>, payload is <-- $pt -->');
print('');
});
} else {
print(
'ERROR MQTT client connection failed - disconnecting, state is ${client.connectionStatus!.state}');
client.disconnect();
}
print('Sleeping....');
await MqttUtilities.asyncSleep(60);
print('Disconnecting');
client.disconnect();
return 0;
}
我会尝试使用 SecurityContext
方法的字节变体。
首先,您需要确保您引用的文件在您的 pubspec.yaml
文件中定义:
flutter:
assets:
- assets/AmazonRootCA1.pem # assuming you placed these files in a folder called assets
- assets/certificate.pem.crt
- assets/private.pem.key
这将确保文件与应用程序打包在一起,以便您可以使用 rootBundle
.
加载它们
然后在您的代码中使用 rootBundle
加载文件并将数据作为字节传递给 SecurityContext
。
final context = SecurityContext.defaultContext;
final clientAuthorities = await rootBundle.load('assets/AmazonRootCA1.pem');
context.setClientAuthoritiesBytes(clientAuthorities.buffer.asUint8List());
final certificateChain = await rootBundle.load('assets/certificate.pem.crt');
context.useCertificateChainBytes(certificateChain.buffer.asUint8List());
final privateKey = await rootBundle.load('assets/private.pem.key');
context.usePrivateKeyBytes(privateKey.buffer.asUint8List());
顺便说一句,我有点困惑为什么你在 flutter 项目中的主要方法不调用 runApp
,而是 returns 和 int
。但是如果你确实在 flutter 应用的 main 方法中使用了上面的代码,你可能需要在使用 rootBundle.load
.
之前在 main
中调用 WidgetsFlutterBinding.ensureInitialized();
我是编程初学者,我正在为一个学校项目构建一个 android 应用程序以使用 esp 32 和 AWS IOT 来打开 on/off LED。我正在使用 mqtt_client 9.6.4,当我 运行 aws_iot.dart 示例时,我能够连接到 AWS IOT 并使用相同的脚本执行操作。当我在 flutter 中使用相同的代码时,我在调试控制台中收到以下错误消息,E/flutter (15280): [ERROR:flutter/lib/ui/ui_dart_state.cc(209)] Unhandled Exception: FileSystemException: Cannot open文件,路径 = 'AmazonRootCA1.pem'(OS 错误:没有这样的文件或目录,errno = 2)
如何解决?
import 'dart:async';
import 'dart:io';
import 'dart:typed_data';
import 'package:flutter/services.dart';
import 'lib/mqtt_server_client.dart';
import 'lib/mqtt_client.dart';
import 'package:pem/pem.dart';
var switch1 = 0;
Future<int> main() async {
const url = 'xxxxxxxxxxxxxxxx.amazonaws.com';
const port = 8883;
const clientId = 'Flutter';
final client = MqttServerClient.withPort(url, clientId, port);
client.secure = true;
client.keepAlivePeriod = 20;
client.setProtocolV311();
client.logging(on: true);
final context = SecurityContext.defaultContext;
context.setClientAuthorities('AmazonRootCA1.pem');
context.useCertificateChain('certificate.pem.crt');
context.usePrivateKey('private.pem.key');
client.securityContext = context;
final connMess =
MqttConnectMessage().withClientIdentifier(clientId).startClean();
client.connectionMessage = connMess;
try {
print('MQTT client connecting to AWS IoT....');
await client.connect();
} on Exception catch (e) {
print('MQTT client exception - $e');
client.disconnect();
}
if (client.connectionStatus!.state == MqttConnectionState.connected) {
print('MQTT client connected to AWS IoT');
const topic = 'esp32/relay1';
const topic2 = 'esp32/relay2';
final builder = MqttClientPayloadBuilder();
builder.addString('{\"status\":\"0\"}');
client.publishMessage(topic, MqttQos.atLeastOnce, builder.payload!);
client.subscribe(topic2, MqttQos.atLeastOnce);
client.updates!.listen((List<MqttReceivedMessage<MqttMessage>> c) {
final recMess = c[0].payload as MqttPublishMessage;
final pt =
MqttPublishPayload.bytesToStringAsString(recMess.payload.message);
print(
'EXAMPLE::Change notification:: topic is <${c[0].topic}>, payload is <-- $pt -->');
print('');
});
} else {
print(
'ERROR MQTT client connection failed - disconnecting, state is ${client.connectionStatus!.state}');
client.disconnect();
}
print('Sleeping....');
await MqttUtilities.asyncSleep(60);
print('Disconnecting');
client.disconnect();
return 0;
}
我会尝试使用 SecurityContext
方法的字节变体。
首先,您需要确保您引用的文件在您的 pubspec.yaml
文件中定义:
flutter:
assets:
- assets/AmazonRootCA1.pem # assuming you placed these files in a folder called assets
- assets/certificate.pem.crt
- assets/private.pem.key
这将确保文件与应用程序打包在一起,以便您可以使用 rootBundle
.
然后在您的代码中使用 rootBundle
加载文件并将数据作为字节传递给 SecurityContext
。
final context = SecurityContext.defaultContext;
final clientAuthorities = await rootBundle.load('assets/AmazonRootCA1.pem');
context.setClientAuthoritiesBytes(clientAuthorities.buffer.asUint8List());
final certificateChain = await rootBundle.load('assets/certificate.pem.crt');
context.useCertificateChainBytes(certificateChain.buffer.asUint8List());
final privateKey = await rootBundle.load('assets/private.pem.key');
context.usePrivateKeyBytes(privateKey.buffer.asUint8List());
顺便说一句,我有点困惑为什么你在 flutter 项目中的主要方法不调用 runApp
,而是 returns 和 int
。但是如果你确实在 flutter 应用的 main 方法中使用了上面的代码,你可能需要在使用 rootBundle.load
.
main
中调用 WidgetsFlutterBinding.ensureInitialized();